最近在看一些行业优秀的开源项目,感触颇深,特别是从代码质量和项目质量来说,系统与系统的解耦合,模块与模块的抽离,代码与代码的复用性等方面,于是想着把之前自己的文章重新梳理一下,当做一个笔记资料,同时也会借鉴一些市面上优秀的文章作参考,如各位同学有不同的见解,也希望不吝赐教,批评指正,多交流.
原型模式,即通过已经创建好的实例作为原型,对这个原型进行克隆(复制),一般用在创建复杂的或者比较耗时的实例创建,因为这种情况下,克隆(复制)一个已经存在的实例使程序运行更高效,也无须知道对象创建的细节。
原型模式的提出,其实也是为了解决以下几个问题:
- 对资源的初始化操作进行优化,因为对类实例化等等都需要消耗不少cpu等资源
- 对性能和安全性要求比较高的场景
- 新建实例需要频繁的进行数据准备或者其他高消耗性操作
- 工厂模式生产实例时
为了解决以上提到的几个问题,原型模式设计初衷, 着重考虑了几个优势:
- 提高实例化性能
- 逃避约束
- 节省资源
但 凡事有利必有弊,虽然原型模式有其优点,但是它的缺点也比较明显:
首先,需要为每个类实现一个可以clone的方法;
其次,需要对原类进行修改,特别对于深克隆实现,每一层对象都要实现克隆,实现会比较麻烦,所以对于深或者浅克隆,都要注意;
下面我们先来看一个例子:
给类添加Clone方法:
我们再来看下主方法怎么实现:
以上我们可以看出,原型的方式,其实是通过地址指针指向同一内存的方式来处理,这里并不要求必须要返回指针对象或者值对象,根据业务需求来定即可,主要关注的点在于,再进行原型克隆时,要考虑好,如果操作克隆实例,会不会对原型造成影响,由此,引申出以下的两个概念
深拷贝与浅拷贝
go
而深拷贝和浅拷贝也可以这样理解:
- 深拷贝就是拷贝整个对象,源对象和拷贝对象没有任何关联,也不会受到任何影响
- 浅拷贝就是拷贝对象指针,其实是引用地址都一样,所以属于牵一发动全身
go
gobreflect
注意: golang完全是按值传递,所以如果深度拷贝的对象中包含有指针的话,那么深度拷贝后,这些指针也会相同,会导致部分数据共享,要注意这一点.
原型模式通常适用应用场景:
- 对象之间相同或相似,即只是个别的几个属性不同的时候。
- 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源。
- 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
- 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。