Design Pattern: Prototype Pattern in Go

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.

NOTES

In this article, we discuss the implementation of the Prototype Pattern in Go.

See the Prototype in other languages in the “Other Code Implementations” section. Or, use the link below to check the details of the Prototype Pattern-

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:

Other Code Implementations

Use the following links to check Prototype pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.