原型模式
- 解决问题
- 对象创建成本比较大,比如需要 DB、权限等外部资源。
- 复杂依赖,比如嵌套依赖等
- 保护性拷贝、记录历史操作场景
- 方法
- 浅拷贝
- 深拷贝
- 还可以类似于 Redis 渐进式 rehash,copy-on-write,需要更改时再处理
1 原型模式
1.1 解决的问题
如果对象的 创建成本较大,且同一个类的不同对象间差别不大(大部分字段相同)的情况下,可以利用已有对象(原型)进行复制(或者叫拷贝、克隆)的方式来创建新的对象,以达到节省创建时间的目的。
简单说,就是实现克隆 clone。
1.2 模式结构

1.3 具体实现
即深拷贝实现。
- 引用类型实现 Cloneable 接口,重写 clone 方法。
public class Assets implements Cloneable{
private int amount; // 数目
private Money money; // 币种
private String kind; // 资金种类
@Override
protected Object clone() {
Assets assets = null;
try {
assets = (Assets)super.clone();
assets.setMoney((Money)this.getMoney().clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return assets;
}
}注:深拷贝需要整个克隆涉及的对象都正确的实现 clone()方法,其只能怪一个没正确实现克隆,都会导致深拷贝失败。
- 序列化,定义一个方法完成对象转二进制流和二进制流转对象,然后返回反序列化后的对象。
public Assets deepClone() {
try {
// 写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 读取二进制流产生新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Assets)ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
1.4 应用场景
简单点说就是以某个对象为原型,克隆出一个一模一样的对象,常见应用场景:
- 资源优化 (对象初始化需使用较多外部资源时,如 IO、数据库、CPU,权限等);
- 复杂依赖 (依赖嵌套,A 创建依赖 B,B 创建依赖 C,一连串的对象 get 和 set);
- 同一对象多个修改者 (多个对象的调用者都需要修改对象的值,克隆多个供使用其使用,保护性拷贝);
- 需保存原始对象状态 (如记录历史操作的场景,通过原型模式快速保存记录);
- 结合工厂模式使用 (定义统一的复制接口,如 clone、copy,使用一个工厂来统一进行拷贝和新对象创建,然后由工厂方法提供给调用者使用)。