Prototype pattern provide a clone method to create a new instance with the current state.
you to duplicate a ob
When to Use
Clone method to copy current state of instance.Similar to Builder pattern: SOLID Principle
Add a Clone method to the example of Builder pattern: Interface Polymorphism + Composition (Combined with Factory Method)
Prototype pattern can be implemented in either Product or Builder (this example), if the Prototype pattern is used in Builder, the Director in the Builder pattern often becomes unnecessary or is used less frequently.
// Abstract Builder
interface Builder {
initProduct(): void // ← Factory Method
setSize(size: number): void
setColor(color: string): void
clone(): Builder // ← Prototype pattern
build(): Product // ← Builder pattern
}
// Concrete Builder
class ChairBuilder implements Builder {
private product!: Chair
initProduct(): void {
// The product can either be encapsulated in the factory or use DI injection.
// - Encapsulation: for fixed type cohesion and simplicity
// - DI: for testability and runtime flexibility
this.product = new Chair()
}
setSize(size: number): void {
this.product.size = size
}
setColor(color: string): void {
this.product.color = color
}
clone(): ChairBuilder {
// Shallow copy (deep enough for this use case)
const copy = new ChairBuilder()
copy.product = { ...this.product }
return copy
}
build(): Product {
return this.product
}
}
// .. Skip the Product codes
// Client
const originalBuilder = new ChairBuilder()
originalBuilder.initProduct()
originalBuilder.setSize(42)
originalBuilder.setColor('Blue')
const clonedBuilder = originalBuilder.clone()
clonedBuilder.setColor('Red')
// Build products
const productA = originalBuilder.build()
const productB = clonedBuilder.build()
console.log('Product A:', productA) // Blue
console.log('Product B:', productB) // Red
Go version: Go Interface Polymorphism + Composition (Combined with Factory Method)
// Abstract Builder
type Builder interface {
InitProduct() // ← Factory Method
SetSize(int)
SetColor(string)
Clone() Builder // ← Prototype pattern
Build() Product // ← Builder pattern
}
// Contrete Builder
type ChairBuilder struct {
product Product
}
func (b *ChairBuilder) InitProduct() {
// The product can either be encapsulated in the factory or use DI injection.
// - Encapsulation: for fixed type cohesion and simplicity
// - DI: for testability and runtime flexibility
b.product = Chair{}
}
func (b *ChairBuilder) SetSize(s int) { b.product.Size = s }
func (b *ChairBuilder) SetSize(s int) { b.product.Size = s }
func (b *ChairBuilder) SetColor(c string) { b.product.Color = c }
func (b *ChairBuilder) Clone() Builder {
// Shallow copy (deep enough for this use case)
copy := *b
return ©
}
func (b *ChairBuilder) Build() Product { return b.product }
// .. Skip the Product codes
// Client
func main() {
originalBuilder := &ChairBuilder{}
originalBuilder.InitProduct()
originalBuilder.SetSize(42)
originalBuilder.SetColor("Blue")
copyBuilder := originalBuilder.Clone()
copyBuilder.SetColor("Red")
productA := originalBuilder.Build()
productB := copyBuilder.Build()
fmt.Printf("Product A: %+v\\n", productA)
fmt.Printf("Product B: %+v\\n", productB)
}
A registry that stores named prototype instances, allowing you to request a copy of a registered prototype by key.