原型模式(Prototype)
定义
Specify the kinds of objects to create using a prototypical instance,and create new objects bycopying this prototype.
(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)
说明
原型对象的简单程度仅次于单例模式和迭代模式。通过原型对象的定义基本已经很清楚原型模式的工作方式,拷贝已有的对象,通过添加不同的状态,来实现不同的表示。
原型对象的核心即克隆(clone),Java中为我们提供了Cloneable接口来标识这个对象是可以拷贝的,注意java中实现这个接口只是说可以进行拷贝,同时还要复写clone()这个方法,具体的过程我们不再这里讨论,请自行查找相关资料。
无论哪种语言拷贝的目的都是在内存中开辟一块相同大小的区域,用来存储一份相同的数据,拷贝一旦完成二者之间可以各自发展,不能相互影响。
开发者经常接触到的拷贝方式有“浅拷贝”和“深拷贝”,浅拷贝和深拷贝主要是指拷贝的范围。
浅拷贝 | 深拷贝 | |
---|---|---|
Java | 只拷贝基本类型数据 | 在拷贝基本类型数据的同时也拷贝引用类型的数据 |
C | 如果结构体中有指针通过“=”或“cpymem”进项的拷贝 | 单个成员分别赋值或者在浅拷贝的基础上指针类型的数据分别赋值 |
原型模式类图:
结构
原型模式包含的角色:
Prototype 抽象原型类 一个克隆自身的接口
ConcretePrototype 具体原型类 一个拥有自我复制功能的具体实现类
Client 调用者 让具体原型类实现自我复制
原型模式的优势
- 可以减少类初始化时对资源和性能的占用。
- 当类的实例只能有几种状态组合中的一种时,建立相应数目的原型并且克隆可能比每次用合适的转台手动实例化更方便。
- 可以将原型模式作为一种备份方式,对重要对象生成某一时刻的快照并保存起来,以便需要的时候恢复到某一个状态。
原型模式的应用
- 通过new的方式实例化对象时如果需要非常繁琐的数据准备,或者需要占用大量资源时可以考虑原型模式。
例如一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
- 系统中有许多场景需要对一个对象进行调用,并且每个场景都要修改对象的状态时,可以考虑使用原型模式复制多个拷贝,供系统调用及修改。
原型模式是一种很简单的设计模式,最常见的使用场景就是进程的创建,操作系统在fork一个新进程时都是通过复制的方式创建一个与自身完全一样的子进程,然后修改子进程的数据来实现进程的差异性,感兴趣的可以查看linux-0.11中copy_process方法中的代码。