Prototype pattern clones an existing object to create a new object, instead of building a new object at runtime. This helps reduce resource usage, as the complex object creation/initiation process is replaced with cloning existing objects. This is very useful for keeping object cached and/or default object.
This article demonstrates Prototype pattern implementations in Go. Check the following examples.
Implementation
Here are the key points of Prototype pattern implementation in go –
- Define an interface and declare a cloning method (usually called “Clone”).
- Define the item structs, for the actual objects.
- Define “Clone” method for the struct, as part of “Prototype” interface implementation. In the method, create new item object, assign values and then return that.
- While using the implementation- call the “Clone” method of the item object, and that will return a new object created using the prototype pattern. Cast the result as the item struct type, if needed.
Simple implementation of Prototype pattern in GoLang-
package main
import "fmt"
// Define an interface for prototype
type Prototype interface {
// Declare Clone method which has return type of the same interface type "Prototype"
Clone() Prototype
}
// Define struct
type SampleStruct1 struct {
Prop1, Prop2 int
}
func NewSampleStruct1() (sampleStruct1 *SampleStruct1) {
sampleStruct1 = &SampleStruct1{}
return
}
// Define "Clone" method as part of "Prototype" implementation
func (sampleStruct1 *SampleStruct1) Clone() Prototype {
cloneObj := NewSampleStruct1()
cloneObj.Prop1 = sampleStruct1.Prop1
cloneObj.Prop2 = sampleStruct1.Prop2
return cloneObj
}
// Demo
func main() {
// Create an original object
originalObj := NewSampleStruct1()
originalObj.Prop1 = 11
originalObj.Prop2 = 99
fmt.Println(originalObj)
// Call the "Clone" method
// also cast the result the original struct
cloneOfOriginalObj := originalObj.Clone().(*SampleStruct1)
cloneOfOriginalObj.Prop1 = 1001
fmt.Println(cloneOfOriginalObj)
}
This will generate following output-
&{11 99}
&{1001 99}
Examples
Here are a few examples of Prototype pattern implementation and usage.
Example #1: Transport
Here we are demonstrating prototype implementation for different vehicles, like Car, Plane etc.
Prototype Interface
- Create file “prototype.go”.
- Define interface “Prototype”.
- Declare the method “Clone” and set the return type as of type “Prototype”.
// prototype.go
package main
type Prototype interface {
Clone() Prototype
}
Car Struct
- Create file “car.go”.
- Define item struct “Car”.
- Define method “NewCar” for the struct. Create a new “Car” object and return it in the method.
- Define method “Clone” for the struct, as part of “Prototype” interface implementation. In the method, create a new “Car” object, set the values from the existing object, and then return it.
// car.go
package main
import "fmt"
type Car struct {
Make int
Model string
Color string
}
func NewCar() (car *Car) {
car = &Car{}
return
}
func (car *Car) Clone() Prototype {
carClone := NewCar()
carClone.Make = car.Make
carClone.Model = car.Model
carClone.Color = car.Color
return carClone
}
func (car *Car) ToString() string {
return fmt.Sprintf("Make: %v | Model: %v | Color: %v", car.Make, car.Model, car.Color)
}
Plane Struct
- Create file “plane.go”.
- Define item struct “Plane”.
- Define method “NewPlane” for the struct. Create a new “Plane” object and return it in the method.
- Define method “Clone” for the struct. Create a new “Car” object, in the “Clone” method, then set the values and return it.
// plane.go
package main
import "fmt"
type Plane struct {
Model string
Color string
}
func NewPlane() (plane *Plane) {
plane = &Plane{}
return
}
func (plane *Plane) Clone() Prototype {
planeClone := NewPlane()
planeClone.Model = plane.Model
planeClone.Color = plane.Color
return planeClone
}
func (plane *Plane) ToString() string {
return fmt.Sprintf("Model: %v | Color: %v", plane.Model, plane.Color)
}
Demo
- Create file “main.go”.
- Create a “Car” object and set values. Here we have saved it in “car1” variable.
- Then call the “Clone” method on the original object “car1”.
- The clone method return type will be of “Prototype” interface. We need to cast the result as “Car”, that’s why we have used “car1.Clone().(*Car)” to cast the interface type as the struct type “(*Car)”.
// main.go
package main
import "fmt"
func main() {
car1 := NewCar()
car1.Make = 2014
car1.Model = "ABCD"
car1.Color = "Red"
fmt.Println(car1.ToString())
carClone := car1.Clone().(*Car)
carClone.Model = "Some Different Model"
carClone.Color = "White"
fmt.Println(carClone.ToString())
}
Output
We will get the following output-
Make: 2014 | Model: ABCD | Color: Red
Make: 2014 | Model: Some Different Model | Color: White
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Transport | GitHub |
Other Code Implementations
Use the following links to check Prototype pattern implementation in other programming languages.