原型模式

Shallow Copy

从话里听出来实现的核心就是克隆,那么就来谈谈克隆的道道,众所周知,在猿类的思想中有深拷贝和浅拷贝的操作,所谓浅拷贝就是复制对象的内容,对象中的引用、容器、数组这些复杂类型是copy他们的地址、而修改浅拷贝后的对象的基本类型或包装类型的值和原来的对象没有关系,但修改复杂类型就会跟原对象牵连了

Deep Copy

深拷贝其实就是复制一个完全不同的对象,这样强调其区别其实不为过,主要在于复杂类型的地址问题,但这两种克隆方式都是创建出了不同的对象,所以说通过具体原型类创建出来的对象和原对象的地址是不同的

说多了不好理解,写看波代码

Prototype.java

public interface Prototype {
    SpecificPrototype clone();
}

SpecificPrototype.java

public class SpecificPrototype implements Prototype {

    private int property1;
    private String property2;
    private Property property;

    public int getProperty1() {
        return property1;
    }

    public void setProperty1(int property1) {
        this.property1 = property1;
    }

    public String getProperty2() {
        return property2;
    }

    public void setProperty2(String property2) {
        this.property2 = property2;
    }

    public Property getProperty() {
        return property;
    }

    public void setProperty(Property property) {
        this.property = property;
    }

    @Override
    public SpecificPrototype clone() {
        SpecificPrototype specificPrototype = new SpecificPrototype();
        specificPrototype.setProperty1(this.property1);
        specificPrototype.setProperty2(this.property2);
        specificPrototype.setProperty(this.property);
        return specificPrototype;
    }
}

/*
 * 实现Cloneable接口可以直接调用封装好的clone方法
 * */
class SpecificPrototype1 implements Cloneable{

    private int property1;
    private String property2;
    private Property property;

    public int getProperty1() {
        return property1;
    }

    public void setProperty1(int property1) {
        this.property1 = property1;
    }

    public String getProperty2() {
        return property2;
    }

    public void setProperty2(String property2) {
        this.property2 = property2;
    }

    public Property getProperty() {
        return property;
    }

    public void setProperty(Property property) {
        this.property = property;
    }

    public SpecificPrototype1 clone() throws CloneNotSupportedException {
        SpecificPrototype1 sp = (SpecificPrototype1) super.clone();
        return sp;
    }
}

/*
* 需要实现Cloneable和Serializable接口
* */
class SpecificPrototype2 implements Cloneable, Serializable{

    private int property1;
    private String property2;
    private Property1 property;

    public int getProperty1() {
        return property1;
    }

    public void setProperty1(int property1) {
        this.property1 = property1;
    }

    public String getProperty2() {
        return property2;
    }

    public void setProperty2(String property2) {
        this.property2 = property2;
    }

    public Property1 getProperty() {
        return property;
    }

    public void setProperty(Property1 property) {
        this.property = property;
    }

    /*
    * 通过字节数组流的方式结合序列化实现深拷贝,通过内存读取的方式实现
    * */
    public SpecificPrototype2 deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (SpecificPrototype2) ois.readObject();
    }
}

Property.java

public class Property{}

//需要实现序列化接口
class Property1 implements Serializable {}

Client.java

public class Client {
    public SpecificPrototype startClone(SpecificPrototype sp){
        return sp.clone();
    }
}

class Client1{
    public SpecificPrototype1 startClone(SpecificPrototype1 sp1) throws CloneNotSupportedException {
        return sp1.clone();
    }
}

class Client2{
    public SpecificPrototype2 startClone(SpecificPrototype2 sp2) throws IOException, ClassNotFoundException {
        return sp2.deepClone();
    }
}

TestPrototype.java

public class TestPrototype {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {

        //简单浅拷贝
        SpecificPrototype sp = new SpecificPrototype();
        sp.setProperty1(1);
        sp.setProperty2("abc");
        Property property = new Property();
        sp.setProperty(property);
        System.out.println(sp);

        Client client = new Client();
        SpecificPrototype prototypeClone = client.startClone(sp);
        System.out.println(prototypeClone);
        System.out.println(sp.getProperty());
        System.out.println(prototypeClone.getProperty());
        System.out.println("DeepClone:" + (sp.getProperty() != prototypeClone.getProperty()));

        //具体原型类实现Cloneable接口的浅拷贝
        SpecificPrototype1 sp1 = new SpecificPrototype1();
        sp1.setProperty1(1);
        sp1.setProperty2("abc");
        Property property1 = new Property();
        sp1.setProperty(property1);
        System.out.println(sp1);

        Client1 client1 = new Client1();
        SpecificPrototype1 prototypeClone1 = client1.startClone(sp1);
        System.out.println(prototypeClone1);
        System.out.println(sp1.getProperty());
        System.out.println(prototypeClone1.getProperty());
        System.out.println("DeepClone:" + (sp1.getProperty() != prototypeClone1.getProperty()));

        //具体原型类实现Cloneable和Serializable接口,通过流的方式实现深拷贝
        SpecificPrototype2 sp2 = new SpecificPrototype2();
        sp2.setProperty1(1);
        sp2.setProperty2("abc");
        Property1 property2 = new Property1();
        sp2.setProperty(property2);
        System.out.println(sp2);

        Client2 client2 = new Client2();
        SpecificPrototype2 prototypeClone2 = client2.startClone(sp2);
        System.out.println(prototypeClone2);
        System.out.println(sp2.getProperty());
        System.out.println(prototypeClone2.getProperty());
        System.out.println("DeepClone:" + (sp2.getProperty() != prototypeClone2.getProperty()));
    }
}

Run result

com.ycw.prototype.SpecificPrototype@3b6eb2ec
com.ycw.prototype.SpecificPrototype@6e8dacdf
com.ycw.prototype.Property@7a79be86
com.ycw.prototype.Property@7a79be86
DeepClone:false
com.ycw.prototype.SpecificPrototype1@21bcffb5
com.ycw.prototype.SpecificPrototype1@668bc3d5
com.ycw.prototype.Property@3cda1055
com.ycw.prototype.Property@3cda1055
DeepClone:false
com.ycw.prototype.SpecificPrototype2@79b4d0f
com.ycw.prototype.SpecificPrototype2@9629756
com.ycw.prototype.Property1@7c0e2abd
com.ycw.prototype.Property1@62ee68d8
DeepClone:true

根据得出的结果可以看出前两个是浅拷贝,只不过后者多了个Cloneable接口,而最后一个是深拷贝,这样的结果就很好对比分析了,原型模式的分析大致如此

12-23 01:48