golang设计模式之原型模式
原型模式
定义
如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式。
原型模式是能基于拷贝来的,对于拷贝我们知道有两种形式,深拷贝和浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
原型模式浅拷贝:
1、省内存,拷贝时间更快;
2、浅拷贝容易出现原始数据被修改的情况,一般不建议使用;
3、浅拷贝可以拷贝不可变对象;
原型模式深拷贝:
1、数据完全隔离;
2、不过数据量大的情况下,深拷贝比起浅拷贝来说,更加耗时,更加耗内存空间;
代码实现
// Cloneable 是原型对象需要实现的接口 type Cloneable interface { Clone() Cloneable } type PrototypeManager struct { prototypes map[string]Cloneable } func NewPrototypeManager() *PrototypeManager { return &PrototypeManager{ prototypes: make(map[string]Cloneable), } } func (p *PrototypeManager) Get(name string) Cloneable { return p.prototypes[name].Clone() } func (p *PrototypeManager) Set(name string, prototype Cloneable) { p.prototypes[name] = prototype }
测试文件
var ( deepCopyManager *PrototypeManager shallowCopyManager *PrototypeManager ) // 深拷贝实现Cloneable type DeepCopy struct { name string } func (t *DeepCopy) Clone() Cloneable { tc := *t return &tc } // 浅拷贝实现Cloneable type ShallowCopy struct { name string } func (t *ShallowCopy) Clone() Cloneable { return t } func TestDeepCopyClone(t *testing.T) { t1 := deepCopyManager.Get("dc") t2 := t1.Clone() // 深拷贝,指向的不是同一个变量的地址 if t1 == t2 { t.Fatal("error! get clone not working") } t21 := t2.(*DeepCopy) t21.name = "ShallowCopy-test" t11 := t1.(*DeepCopy) // 深拷贝name,不会影响到copy前的变量 if t11.name == t21.name { t.Fatal("shallowCopy err") } } func TestShallowCopyClone(t *testing.T) { t1 := shallowCopyManager.Get("sc") t2 := t1.Clone() // 浅拷贝,变量地址的指向不变 if t1 != t2 { t.Fatal("error! get clone not working") } t21 := t2.(*ShallowCopy) t21.name = "ShallowCopy-test" t11 := t1.(*ShallowCopy) // 深拷贝name,copy之前的变量和copy之后的变量同时更改 if t11.name != t21.name { t.Fatal("shallowCopy err") } } func init() { deepCopyManager = NewPrototypeManager() dc := &DeepCopy{ name: "deepCopy", } deepCopyManager.Set("dc", dc) shallowCopyManager = NewPrototypeManager() sc := &ShallowCopy{ name: "shallowCopy", } shallowCopyManager.Set("sc", sc) }
优点
1、使用原型模式创建对象比直接new一个对象在性能上要好的多,因为是直接进行的内存拷贝,比初始化性能上会好很多;
2、简化对象的创建,对于创建对象就像我们在编辑文档时的复制粘贴一样简单。
缺点
克隆包含循环引用的复杂对象可能会非常麻烦。
适用场景
1、在项目中,如果存在大量相同或相似对象的创建,如果用传统的构造函数来创建对象,会比较复杂和耗费资源,用原型模式生产对象就很高效;
2、对象创建过程比较麻烦,但复制比较简单的时候;