一、定义
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
二、最简单的原型模式
原型模式即通过复制原型对象创建一个和原型相同的或相似的对象,因此,我们可以给类(struct)增加一个方法,Clone()来返回对象的复制品即可,代码如下:可以看到通过调用Clone生成了一个和原来一样的一个对象。
func main1() {
person1 := new(Person)
person1.Age = 12
person1.Nation = "China"
person1.Name="test"
//通过原型去创建
person2 := person1.Clone()
fmt.Println(person2.Name)
}
type Person struct {
Name string
Age uint8
Nation string
}
func (person *Person) Clone() *Person {
newPerson := new(Person)
newPerson.Name = person.Name
newPerson.Age = person.Age
newPerson.Nation = person.Nation
return newPerson
}
三、带抽象接口的原型模式
我们知道java中有一个Cloneable接口,实现该接口,即完成了原型模式的定义。现在我们模仿java中的定义来重新完善一下我们的原型模式。代码如下:注意的是,java中的Clone返回的是最顶级的Object对象,因此我们这里返回的是interface{},在使用时,需要转换对象:即变量名.(转换的类型名称)
func main2() {
person1 := new(Person)
person1.Age = 12
person1.Nation = "China"
person1.Name="test"
dog1 := new(Dog)
dog1.Name = "dog1"
dog1.Master = person1
dog2,ok := dog1.Clone().(*Dog) //注意这里是指针,因为方法返回的是指针类型
if !ok{
fmt.Println("转换失败。。。。")
}
fmt.Println(dog2.Name)
fmt.Println(dog2.Master.Name)
}
type Dog struct {
Name string
Master *Person
}
type Cloneable interface {
Clone() interface{}
}
func (dog *Dog) Clone() interface{} {
newDog := new(Dog)
newDog.Name = dog.Name
newDog.Master = dog.Master//这里用的是浅拷贝
return newDog
}
四、带原型管理器的原型模式
通过上面的原型模式,我们已经很方便的创建对象了,但是,当我们需要创建不同类型的对象时,我们需要调用不同的对象来进行扩展,多了的情况下很不方便。
在原型模式的基础上增加了一个原型管理器 PrototypeManager 类。该类用map保存多个不同的原型,这样,我们就可以通过该管理器获取不同的类型原型。代码如下:通过传入不同的类型参数名,即可获取到不同的类型原型(cat或dog)
//带原型管理器的原型模式
func main() {
cat1 := new(Cat)
cat1.Name="cat1"
dog1 := new(Dog)
dog1.Name = "dog1"
//设置原型管理类
manager:= new(AnimnalProtoManager)
manager.SetProto("cat",cat1)
manager.SetProto("dog",dog1)
//从原型管理类中获取所需的原型
dog2,ok := manager.GetProto("dog").Clone().(IAnimal)
if !ok{
fmt.Println("转换失败")
}
dog2.Speak()
cat2,ok := manager.GetProto("cat").Clone().(*Cat)
if !ok{
fmt.Println("转换失败")
}
fmt.Println(cat2.Name)
cat2.Speak()
}
type IAnimal interface {
Cloneable
Speak()
}
func (dog *Dog) Speak() {
fmt.Println("汪汪汪。。。。")
}
type Cat struct {
Name string
Master *Person
}
func (cat *Cat) Clone() interface{} {
newCat := new(Cat)
newCat.Name = cat.Name
newCat.Master = cat.Master//这里用的是浅拷贝
return newCat
}
func (cat *Cat) Speak() {
fmt.Println("喵喵喵^^^^^^")
}
//可以根据传入不同的参数来生成指定的狗原型,比如,田园犬
type AnimnalProtoManager struct {
protoMap map[string]IAnimal
}
func (manager *AnimnalProtoManager) GetProto(class string) IAnimal {
proto,ok := manager.protoMap[class]
if ok {
return proto
}
return nil
}
func (manager *AnimnalProtoManager) SetProto(class string, proto IAnimal) {
if manager.protoMap == nil{
manager.protoMap = make(map[string]IAnimal)
}
manager.protoMap[class] = proto
}