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()
異なるインスタンス間で依然として干渉を。