I think the Prototype Design Pattern is to use the Clone() function to create objects from other objects instead of using the New() function , so the New() function of the object is only used once, and the memory addresses of the two objects are not the same
Prototype Design Pattern are often used to create complex objects, so this example simulates creating complex objects by reading an XML file
<?xml version="1.0" encoding="UTF-8" ?>
<product>
<name>Cookie</name>
<id>168</id>
<weight>75.4</weight>
<high>18.2</high>
<description>Good cookies</description>
</product>
The design pattern demo doesn't use third-party frameworks whenever possible
prototype.go
package designpattern
import (
"encoding/xml"
"fmt"
"os"
)
type Product struct {
XMLName xml.Name `xml:"product"`
Id int `xml:"id"`
Name string `xml:"name"`
Weight float64 `xml:"weight"`
High float64 `xml:"high"`
Description string `xml:"description"`
}
func (source *Product) Clone() *Product {
return &Product{Id: source.Id, Name: source.Name, Weight: source.Weight, High: source.High, Description: source.Description}
}
func NewProduct() (*Product, error) {
println("Create object from xml file...")
file, err := os.Open("../config/Product.xml")
defer file.Close()
if err != nil {
return nil, err
}
fileinfo, err := file.Stat()
if err != nil {
return nil, err
}
bytes := make([]byte, fileinfo.Size())
bytesread, err := file.Read(bytes)
if bytesread == 0 {
return nil, fmt.Errorf("Nothing to read")
}
if err != nil {
return nil, err
}
var product *Product
xml.Unmarshal(bytes, &product)
return product, nil
}
prototype_test.go
package designpattern_test
import (
"fmt"
designpattern "ptarmigan-golang-design-pattern/src"
"testing"
)
func TestClone(t *testing.T) {
sourceProduct, err := designpattern.NewProduct()
if err != nil {
t.Error(err)
}
targetProduct := sourceProduct.Clone()
fmt.Printf("Pointer of Source Product: %p \n", &sourceProduct)
fmt.Printf("Pointer of Traget Product: %p \n", &targetProduct)
if &targetProduct == &sourceProduct {
t.Error(fmt.Errorf("The target product and the source product are the same object"))
}
if targetProduct.Name != sourceProduct.Name {
t.Error(fmt.Errorf("Target product attributes are not the same as source products"))
}
println("Clone Product Success!")
}
The results of this unit test are as follows:
Create object from xml file...
Pointer of Source Product: 0xc0000c4028
Pointer of Traget Product: 0xc0000c4048
Clone Product Success!
PASS