设计模式系列3-原型模式

原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些 原型创建新的对象。
使用场景:

  1. 类初始化消耗资源较多
  2. new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
  3. 构造函数比较复杂
  4. 循环体中生产大量对象时

在 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; 
}
posted @ 2021-09-23 20:57  狻猊的主人  阅读(35)  评论(0编辑  收藏  举报