原型(Prototype)设计模式

原型(Prototype)设计模式

1.0.0:什么是原型?

????用一个已经创建的对象,通过复制的手段创建一个和原对象相同或者相似的对象。

2.0.0:为什么要用原型?

  • 对象创建的时间消耗要大于克隆(clone)的消耗?reason?
  • 对象创建的时候是一个初始态,克隆是一个瞬时态。比如就是,你需要创建一个person,new 的话,person是一个初始态 A,你可能对person进行修改(update),修改之后person的状态发生了改变为 B。那么如果进行克隆的话,你的状态会停留在当前的状态。这就是clone和new的区别。在不同情况,可以分别处理。
  • clone会保留对象的状态信息,数据和原对象是一致的,如果对象中含有引用类型的数据的话,那么他的指向地址是一样的,那么比如说有对象A和他的克隆者B。A对他的引用类型进行修改,同时也会影响到B。
    eg:A对象有一只鸡,他把鸡杀了,鸡处于死亡状态,那么他的克隆对象的鸡也会死亡。哈哈哈,在某些时候,我们不想他们一样,那么就是需要重新创建新的鸡的引用,存放在堆内存中的数据也就是不同的。如何做?
    num 对象的深复制
  • 序列化方式--> 序列化 --> 反序列化
  • 手动方式--> 所有的引用对象都实现cloneable --> 很麻烦,而且有一些基础类也没有实现cloneable
    num 引用的重新创建和指定,引用比较多的时候,会比较麻烦

3.0.0原型的实现代码

3.1.0 浅克隆

@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable {
    private int id;
    private String name;
    private Attribute attribute;

    @Override
    public String toString() {
        return "ProtoType(" + this.hashCode() + "){" +
                "id=" + id +
                ", name='" + name + '\'' + name.hashCode() +
                ", attribute=" + attribute +
                '}';
    }

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

    @Setter
    @Getter
    protected class Attribute {
        private int level;
        private String love;

        @Override
        public String toString() {
            return "Attribute(" + this.hashCode() + "){" +
                    "level=" + level +
                    ", love='" + love + '\'' + love.hashCode() +
                    '}';
        }
    }
}
@Slf4j
public class ProtoTypeTest {
    public static void main(String[] args) {
        ProtoType protoType = new ProtoType();
        protoType.setId(1);
        protoType.setName("alice");
        ProtoType.Attribute attribute = protoType.new Attribute();
        attribute.setLevel(1);
        attribute.setLove("[email protected]");
        protoType.setAttribute(attribute);
        log.info("protoType {}", protoType);
        try {
            Object clone = protoType.clone();
            log.info("clone {}", clone);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
//run 001
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//run 002
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//run 003
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
    }
}

3.2.0 深克隆

3.2.1 序列化深克隆

@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable, Serializable {
    private int id;
    private String name;
    private Attribute attribute;

    @Override
    public String toString() {
        int i = this.hashCode();
        log.info("----{}", System.identityHashCode(this));
        return "ProtoType(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
                "id=" + id +
                ", name='" + name + '\'' + name.hashCode() +
                ", attribute=" + attribute +
                '}';
    }

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

    public Object deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return ois.readObject();
    }

    @Setter
    @Getter
    protected class Attribute implements Serializable {
        private int level;
        private String love;

        @Override
        public String toString() {
            int i = this.hashCode();
            return "Attribute(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
                    "level=" + level +
                    ", love='" + love + '\'' + love.hashCode() +
                    '}';
        }
    }
}
@Slf4j
public class ProtoTypeDeepTest {
    public static void main(String[] args) {
        ProtoType protoType = new ProtoType();
        protoType.setId(1);
        protoType.setName("alice");
        ProtoType.Attribute attribute = protoType.new Attribute();
        attribute.setLevel(1);
        attribute.setLove("[email protected]");
        protoType.setAttribute(attribute);
        log.info("protoType {}", protoType);
        ProtoType p2 = new ProtoType();
        try {
            Object clone = protoType.deepClone();
            log.info("clone {}", clone);
        } catch (Exception e) {
            e.printStackTrace();
        }
        /**run1
         protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
         clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
         */

        /** run2
         protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
         clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
         */

        /** run3
         protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
         clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
         */

        /** run4 增加   ProtoType p2 = new ProtoType()之后 内存地址也一样
         protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
         clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
         */

        //涉及到的一点 内存的分配规则
    }
}

3.2.2 手动深克隆

@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable {
    private int id;
    private String name;
    private Attribute attribute;

    @Override
    public Object clone() throws CloneNotSupportedException {
        ProtoType clone = (ProtoType) super.clone();
        clone.setAttribute(attribute.clone());
        return clone;
    }

    public Object deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return ois.readObject();
    }

    @Override
    public String toString() {
        return "ProtoType(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
                "id=" + id +
                ", name='" + name + '\'' + name.hashCode() +
                ", attribute=" + attribute +
                '}';
    }

    @Setter
    @Getter
    protected class Attribute implements Cloneable {
        private int level;
        private String love;

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

        @Override
        public String toString() {
            return "Attribute(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
                    "level=" + level +
                    ", love='" + love + '\'' + love.hashCode() +
                    '}';
        }
    }
}


@Slf4j
public class ProtoTypeDeepTest2 {
    public static void main(String[] args) {
        ProtoType protoType = new ProtoType();
        protoType.setId(1);
        protoType.setName("alice");
        ProtoType.Attribute attribute = protoType.new Attribute();
        attribute.setLevel(1);
        attribute.setLove("[email protected]");
        protoType.setAttribute(attribute);
        log.info("protoType {}", protoType);
        try {
            Object clone = protoType.clone();
            log.info("clone {}", clone);
        } catch (Exception e) {
            e.printStackTrace();
        }
        /**
         *protoType ProtoType(752848266|||752848266){id=1, name='alice'92903040, attribute=Attribute(815033865|||815033865){level=1, love='[email protected]'-1847814268}}
         *clone ProtoType(340870931|||340870931){id=1, name='alice'92903040, attribute=Attribute(1768305536|||1768305536){level=1, love='[email protected]'-1847814268}}
         *
         *protoType ProtoType(752848266|||752848266){id=1, name='alice'92903040, attribute=Attribute(815033865|||815033865){level=1, love='[email protected]'-1847814268}}
         *clone ProtoType(340870931|||340870931){id=1, name='alice'92903040, attribute=Attribute(1768305536|||1768305536){level=1, love='[email protected]'-1847814268}}
         */
    }
}
相关文章
相关标签/搜索