设计模式系列3-原型模式
原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些 原型创建新的对象。
使用场景:
- 类初始化消耗资源较多
- new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数比较复杂
- 循环体中生产大量对象时
在 Spring 中,原型模式应用得非常广泛。例如 scope=“prototype”,在我们经常用的JSON.parseObject()也是一种原型模式。
大家都知道齐天大圣。首先它是一只猴子,有七十二般变化,把一根 毫毛就可以吹出千万个泼猴,手里还拿着金箍棒,金箍棒可以变大变小。这就是我们耳 熟能详的原型模式的经典体现
- 猴子类 Monkey
public class Monkey {
public int height;
public int weight;
public Date birthday;
}
- 金箍棒 JinGuBang
public class JinGuBang implements Serializable {
public float h = 100;
public float d = 10;
}
- 齐天大圣 QiTianDaSheng
public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {
public JinGuBang jinGuBang;
public QiTianDaSheng() {
//只是初始化
this.birthday = new Date();
this.jinGuBang = new JinGuBang();
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 调用克隆方法
return this.deepClone();
}
}
简单克隆
简单克隆也称浅克隆
。只是完整 复制了值类型数据,没有赋值引用对象。换言之,所有的引用对象仍然指向原来的对象。
这样就好比每个猴子分身使用的都是同一个金箍棒,这样肯定是不行的
public QiTianDaSheng shallowClone(QiTianDaSheng target) {
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
qiTianDaSheng.height = target.height;
qiTianDaSheng.weight = target.height;
qiTianDaSheng.jinGuBang = target.jinGuBang;
qiTianDaSheng.birthday = new Date();
return qiTianDaSheng;
}
深度克隆
public Object 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);
QiTianDaSheng copy = (QiTianDaSheng) ois.readObject();
copy.birthday = new Date();
return copy;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
克隆破坏单例模式
如果我们克隆的目标的对象是单例对象,那意味着,深克隆就会破坏单例。实际上防止 克隆破坏单例解决思路非常简单,禁止深克隆便可。要么你我们的单例类不实现 Cloneable 接口;要么我们重写 clone()方法,在 clone 方法中返回单例对象即可
@Override
protected Object clone() throws CloneNotSupportedException {
return INSTANCE;
}