学习设计模式之原型模式

原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

结构图
在这里插入图片描述

  1. Prototype:原型类,声明一个克隆自身的接口
  2. ConcretePrototype:具体原型类,实现一个克隆自身的操作
  3. Client:客户端,让一个原型克隆自身从而创建一个新的对象

代码实现

public class PrototypeA01 implements Cloneable {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "PrototypeA01{" +
                "id=" + id +
                '}';
    }
}

public class TestMain {
    public static void main(String[] args) throws CloneNotSupportedException {
        PrototypeA p = new PrototypeA();
        p.setId(1);
        System.out.println(p);
        PrototypeA clonep = (PrototypeA) p.clone();
        System.out.println(clonep);
    }
}

运行结果
PrototypeA{id=‘1’}
PrototypeA{id=‘1’}

Process finished with exit code 0

关键点在于,实现 Cloneable 接口以及用 object 的 clone 方法。这样就可以不用实例化对象,直接克隆就可以了,只需要实现这个接口就可以完成原型模式了!

浅克隆与深克隆
在原型模式中有两个概念我们需要了解一下,就是浅克隆和深克隆的概念。如果对象里的属性都是值类型那么没有问题,如果对象里有引用类型则是复制引用而不是复制引用的对象,因此原始对象及其复制对象引用同一个对象。

浅克隆
在这里插入图片描述
深克隆
在这里插入图片描述

例如

public class PrototypeA01 implements Cloneable {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "PrototypeA01{" +
                "id=" + id +
                '}';
    }
}

public class PrototypeA01 {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    
    @Override
    public String toString() {
        return "PrototypeA01{" +
                "id=" + id +
                '}';
    }
}

public class TestMain {
    public static void main(String[] args) throws CloneNotSupportedException {
        PrototypeA p = new PrototypeA();
        PrototypeA01 pa01 = new PrototypeA01();
        pa01.setId(2);
        p.setId(1);
        p.setPrototypeA01(pa01);
        System.out.println(p);
        PrototypeA clonep = (PrototypeA) p.clone();
        System.out.println(clonep);
        // 现在来修改这个对象
        pa01.setId(3);
        System.out.println(p);
        System.out.println(clonep);
    }
}

运行结果
PrototypeA{id=1, prototypeA01=PrototypeA01{id=2}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=2}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=3}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=3}}

Process finished with exit code 0

从运行结果来看原始对象和克隆对象的属性都改变了。深克隆,我就不用多说了吧,就是什么都是单独的!全部复制,然后各自独立。你修改克隆对象对于原型对象没有丝毫影响。

代码实现之需要在对应的属性类上再次实现 Cloneable 接口以及用 object 的 clone 方法就可以了。

public class PrototypeA implements Cloneable {

    private int id;

    private PrototypeA01 prototypeA01;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public PrototypeA01 getPrototypeA01() {
        return prototypeA01;
    }

    public void setPrototypeA01(PrototypeA01 prototypeA01) {
        this.prototypeA01 = prototypeA01;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        PrototypeA clone = (PrototypeA) super.clone();
        clone.setPrototypeA01((PrototypeA01) getPrototypeA01().clone());
        return clone;
    }

    @Override
    public String toString() {
        return "PrototypeA{" +
                "id=" + id +
                ", prototypeA01=" + prototypeA01 +
                '}';
    }
}

public class PrototypeA01 implements Cloneable {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "PrototypeA01{" +
                "id=" + id +
                '}';
    }
}

public class TestMain {
    public static void main(String[] args) throws CloneNotSupportedException {
        PrototypeA p = new PrototypeA();
        PrototypeA01 pa01 = new PrototypeA01();
        pa01.setId(2);
        p.setId(1);
        p.setPrototypeA01(pa01);
        System.out.println(p);
        PrototypeA clonep = (PrototypeA) p.clone();
        System.out.println(clonep);
        // 现在来修改这个对象
        pa01.setId(3);
        System.out.println(p);
        System.out.println(clonep);
    }
}

运行结果
PrototypeA{id=1, prototypeA01=PrototypeA01{id=2}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=2}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=3}}
PrototypeA{id=1, prototypeA01=PrototypeA01{id=2}}

Process finished with exit code 0

从结果来看都是单独的!全部复制,然后各自独立。

总结
原型模式的Prototype类必须继承Cloneable接口,并对接口中的clone方法进行实现。

优点
使用原型模型创建一个对象比直接new一个对象更有效率,因为它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

缺点
在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

猜你喜欢

转载自blog.csdn.net/qq_16830879/article/details/86742728