[Golangデザインパターン] 5.プロトタイプパターン

5.プロトタイプモード

プロトタイプモード。プロトタイプインスタンスを使用して、作成されるオブジェクトのタイプを指定し、これらのプロトタイプオブジェクトをコピーして新しいオブジェクトを作成します。

たとえば、履歴書があり、個人情報の部分は同じである必要があるため、これをプロトタイプとして使用し、プロトタイプのClone()メソッドを使用して新しいインスタンスを生成し、新しいインスタンスの一意の情報を変更して、目的。さらに、異なる例の変更は互いに干渉してはなりません具体的な操作は次のとおりです。

パスの下にprototype\新しいファイルを作成します。prototype.goパッケージ名はprototype次のとおりです

package prototype

// ...

履歴書には、名前、性別、学校、応募企業、求人などの情報が含まれている必要があります。ここでは、学校情報を格納するための構造を使用します。

type School struct {
	Name    string
	Address string
	Level   string
}

// 创建School实例,返回对应指针
func NewSchool(name, address, level string) *School {
	return &School{
		Name:    name,
		Address: address,
		Level:   level,
	}
}

プロトタイプのClone()メソッドを使用して新しいインスタンスをコピーするため、異なるインスタンスが互いに干渉しないようにするために、ディープコピーを使用する必要があります。学校もClone()メソッドを実装する必要があるため、プロトタイプはSchool()になりますクローンを作成するとき、School's Clone()メソッドが呼び出されます。

// School也要实现Clone()方法
func (s *School) Clone() *School {
	return NewSchool(s.Name, s.Address, s.Level)
}

// 重写School的String()方法,便于输出信息
func (s *School) String() string {
	return "{" + s.Name + " " + s.Address + " " + s.Level + "}"
}

次に、Resume構造と対応する新しいResumeインスタンスメソッドがあります。

ここで、Goの構造はポインター型ではなく値型であることに注意してください。新しい複合構造を作成する場合、構造の値は過去にコピーされるため、スクールポインターがここで使用されます。また、一定のスペースを節約できます。

type Resume struct {
	Name   string
	Gender string
	// 由于Go中结构体是值类型而不是指针类型,创建新的复合结构体时,会把值复制一份过去,所以这里使用School指针
	School        *School
	Apply4Company string
	Apply4Job     string
}

func NewResume(name, gender string, school *School, company, job string) *Resume {
	return &Resume{
		Name:          name,
		Gender:        gender,
		School:        school,
		Apply4Company: company,
		Apply4Job:     job,
	}
}

プロトタイプのClone()メソッドについて注意する点は、r.School.Clone()コピーr.School(実際にはポインター)を使用して配置する必要があることです

// 原型的Clone()方法
func (r *Resume) Clone() *Resume {
	// 注意这里的r.School.Clone()
	return NewResume(r.Name, r.Gender, r.School.Clone(), r.Apply4Company, r.Apply4Job)
}

パスのprototype同じディレクトリに新しいmain.goテストメソッドを作成します

package main

import (
	"fmt"
	"github.com/loveshes/go-design-patterns/pattern/prototype-pattern/prototype"
)

func main() {
	ncu := prototype.NewSchool("南昌大学", "江西省南昌市", "211")
	proto := prototype.NewResume("王英俊", "男", ncu, "", "")

	// 简历一
	alibaba := proto.Clone()
	alibaba.Apply4Company = "Alibaba"
	alibaba.Apply4Job = "Java Web"
	fmt.Println("alibaba:", *alibaba)

	// 简历二
	bytedance := proto.Clone()
	// 修改复合结构体中的School.Level字段,看alibaba中的是否也会改变
	bytedance.School.Level = "双一流"
	bytedance.Apply4Company = "ByteDance"
	bytedance.Apply4Job = "Go"
	fmt.Println("修改School.Level后,alibaba:", *alibaba)
	fmt.Println("修改School.Level后,bytedance:", *bytedance)
}

出力は

alibaba: {王英俊 男 {南昌大学 江西省南昌市 211} Alibaba Java Web}
修改School.Level后,alibaba: {王英俊 男 {南昌大学 江西省南昌市 211} Alibaba Java Web}
修改School.Level后,bytedance: {王英俊 男 {南昌大学 江西省南昌市 双一流} ByteDance Go}

CV2のSchool.Levelへの変更がCV1に影響しなかったことがわかります。

さらに、r.Clone()中央のものr.School.Clone()変更r.Schoolして、効果があるかどうか確認できます。

構造自体は値移動型であるため、Resume構造が*School変化しSchool、使用しない場合、r.School.Clone()異なるインスタンス間で依然として干渉を。

完全な例

おすすめ

転載: www.cnblogs.com/loveshes/p/12756323.html