模式定义
原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
模式结构
原型模式最主要的一点就是要求 原型对象 拥有克隆自己的能力,这样就可以调用其克隆方法来创建一个和原型对象类型相同的实例。原型模式主要有两种结构:简单形式和登记形式。
简单形式
简单形式中的三个角色:
- 客户角色,即提出创建对象请求的类;
- 抽象原型,即提供创建对象能力的角色,通常是接口或抽象类,通常可以使用Java提供的
Cloneable
接口,也可以自己实现; - 具体原型,具体要创建出来的对象类型,实现(或覆盖)了抽象原型定义的接口方法。
具体代码示例:
抽象原型
1 | public interface AbsPrototype { |
具体原型
1 | public class RealPrototype implements AbsPrototype { |
客户角色
1 | public class SimpleClient { |
登记形式
大体上和简单形式相同,只不过多了一个管理类,用键值对来将 抽象原型对象 不同的实现保存起来,然后要创建不同类型的 具体原型对象,只要根据相应的键来进行复制即可。
抽象原型对象的另一种实现
1 | public class AnotherPrototype implements AbsPrototype { |
不同类型原型对象管理角色
1 | public class PrototypeManager { |
客户端角色
1 | public class CheckoutClient { |
改进版
1 | public class PrototypeManager { |
相应的CheckoutClient
改为:
1 | public class CheckoutClient { |
原型对象的创建都集中在PrototypeManager
中,新增支持的原型对象只需要定义新增的原型对象,然后相应的添加到PrototypeManager
中即可。
模式总结
- 应用场景,当需要大范围的或者平凡的创建某类对象时;
- 应用先决条件,原型对象必须支持克隆自己的方法;
延伸拓展
上面说了,原型模式实现的前提是原型对象必须支持克隆自己的方法。这里的克隆有两种形式:浅克隆和深克隆。
浅克隆与深克隆
浅克隆:只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。
深克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深度克隆把要复制的对象所引用的对象都复制了一遍,而这种对被引用到的对象的复制叫做间接复制。
深度克隆要深入到多少层,是一个不易确定的问题。在决定以深度克隆的方式复制一个对象的时候,必须决定对间接复制的对象时采取浅度克隆还是继续采用深度克隆。因此,在采取深度克隆时,需要决定多深才算深。此外,在深度克隆的过程中,很可能会出现循环引用的问题,必须小心处理。
一般的Object的clone()
就是浅克隆,而Java中通常通过序列化来实现对象的深克隆,即先将对象序列化到流中,然后再从反序列化读出对象。对于不能被序列化的对象,需要用transient
将其排除在克隆之外。