Golang原型模式

210 阅读1分钟

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