第五章 原型模式 - 对象的克隆
原型模式:使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。属于一种对象创建型模式。
一、概述
1.1 原理
原型模式的工作原理很简单:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。由于在软件系统中我们经常会遇到需要创建多个相同或者相似对象的情况,因此原型模式在真实开发中的使用频率还是非常高的。原型模式是一种“另类”的创建型模式,创建克隆对象的工厂就是原型类自身,工厂方法由克隆方法来实现。
1.2 原型模式中的几个角色
- Prototype - 抽象原型类
- 声明克隆方法的接口,是所有具体原型类的公共父类
- ConcretePrototype - 具体原型类
- 实现抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象
- Client - 客户类
- 让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。
1.3 案例
@Getter
@Setter
class WeeklyLog implements Clonealbe{
private String name;
private String date;
private String content;
publci WeekLog clone(){
Object obj = null;
try{
obj = super.clone();
return (WeekLog)obj;
} catch (CloneNotSupportedException e){
System.out.println("不支持复制");
return null;
}
}
}
二、浅克隆与深克隆
2.1 浅克隆
在浅克隆中,如果原型对象的成员是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象。也就是说,原型对象的引用类型变量与克隆对象中的变量指向同一内存地址。
即值类型成员变量会被复制,但是引用成员变量不会。
2.2 深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象。
如果需要实现深克隆,可以通过序列化(Serialization)等方式实现:将对象写入到流,再从流中读出。
Java语言提供的 Cloneable 接口和 Serializable 接口都是空接口,也称为标识接口。标识接口无任何方法定义,只提供告诉JRE这些接口的实现类是否支持克隆、序列化等功能。
三、总结
优点
- 当创建新对象较为复杂时,可以使用原型模式简化对象的创建过程,复制一个已有实例以提高新实例的创建效率
- 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中
- 原型模式提供了简化的创建结构,工厂方法模式需要与产品等级结构对应的工厂等级结构,而原型模式则直接通过封装在原型类中的克隆方法实现
- 深克隆方式可以保存对象的状态
缺点
- 需要每个类配置一个克隆方法,且位于类内部,当对类进行改造时需要修改源码,违反了“开闭原则”
- 实现深克隆时较为复杂,对象的每一层子对象都需要进行深克隆
适用场景
- 创建新对象成本较大(如初始化时间长、占用CPU资源多或网络资源占用多),新对象能够通过原型模式进行复制,复制相似对象再进行修改
- 可以通过原型模式+备忘录模式,来实现保存对象的状态
- 避免使用工厂模式来创建对象