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.

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:

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.