设计模式之创建型模式---原型模式模式

孤街浪徒 提交于 2019-12-31 22:52:53

原型模式(Prototype)
原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
原型模式主要涉及两个概念,浅拷贝与深拷贝。
浅拷贝:是指将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深拷贝:是指将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
说完理论,接着来举例:
首先先创建一个非基本类型的对象(为了能够实现深拷贝,此处创建的对象必须序列化):

/**
 * @author chenglezheng
 */
public class Clone implements Serializable {

    private String name;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


}

接着我们创建一个浅拷贝对象

/**
 * @author chenglezheng
 */
public class CloneShallow implements Cloneable{

    private Clone clone;

    private int test;

    public int getTest() {
        return test;
    }

    public void setTest(int test) {
        this.test = test;
    }

    public Clone getClone() {
        return clone;
    }

    public void setClone(Clone clone) {
        this.clone = clone;
    }

    public void print(){
        System.out.println(clone);
        System.out.println(clone.getName());
        System.out.println(test);
    }

    @Override
    protected CloneShallow clone()  {
        try{
            return (CloneShallow) super.clone();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

再来创建一个深拷贝(深拷贝需要通过流的形式创建

/**
 * @author chenglezheng
 */
public class CloneDeep implements Serializable {

    private Clone clone;

    public Clone getClone() {
        return clone;
    }

    public void setClone(Clone clone) {
        this.clone = clone;
    }

    private int test;

    public int getTest() {
        return test;
    }

    public void setTest(int test) {
        this.test = test;
    }

    public void print(){
        System.out.println(clone);
        System.out.println(clone.getName());
        System.out.println(test);
    }

    protected CloneDeep clone(CloneDeep clone)  {
        CloneDeep cloneDeep=null;
        try{
            /* 写入当前对象的二进制流 */
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(clone);
            /* 读出二进制流产生的新对象 */
             ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
             ObjectInputStream ois = new ObjectInputStream(bis);
            cloneDeep=(CloneDeep)ois.readObject();
            return cloneDeep;  //此处需要做流关闭,因为演示所以没弄
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
}

最后准备测试:

/**
 * @author chenglezheng
 */
public class PrototypeTest {

    public static void main(String[] args) {

        Clone clone=new Clone();
        clone.setName("张三");
        System.out.println("浅拷贝测试结果...");
        CloneShallow cloneShallow =new CloneShallow();
        cloneShallow.setClone(clone);
        cloneShallow.print();
        CloneShallow cloneShallow1 = cloneShallow.clone();
        cloneShallow1.print();
        System.out.println("深拷贝测试结果...");
        CloneDeep cloneDeep=new CloneDeep();
        cloneDeep.setClone(clone);
        cloneDeep.print();
        CloneDeep cloneDeep1=cloneDeep.clone(cloneDeep);
        cloneDeep1.print();
        System.out.println("******************************");
        System.out.println("浅拷贝测试结果1...");
        clone.setName("李四");
        cloneShallow.setClone(clone);
        cloneShallow.setTest(10);
        cloneShallow.print();
        cloneShallow1.print();
        System.out.println("深拷贝测试结果1...");
        cloneDeep.setClone(clone);
        cloneDeep.setTest(10);
        cloneDeep.print();
        cloneDeep1.print();


    }
}

运行结果:
浅拷贝测试结果…
com.lc.clz.create.prototype.Clone@4554617c
张三
0
com.lc.clz.create.prototype.Clone@4554617c
张三
0
深拷贝测试结果…
com.lc.clz.create.prototype.Clone@4554617c
张三
0
com.lc.clz.create.prototype.Clone@378bf509
张三
0


浅拷贝测试结果1…
com.lc.clz.create.prototype.Clone@4554617c
李四
10
com.lc.clz.create.prototype.Clone@4554617c
李四
0
深拷贝测试结果1…
com.lc.clz.create.prototype.Clone@4554617c
李四
10
com.lc.clz.create.prototype.Clone@378bf509
张三
0
结果分析:
在这里插入图片描述
改变原对象中的name属性值,分别设置给浅复制对象和深复制对象
clone.setName(“李四”);
cloneShallow.setClone(clone);
cloneShallow.setTest(10);

cloneDeep.setClone(clone);
cloneDeep.setTest(10);
在这里插入图片描述
除此之外,不管浅复制还是深复制,基本的数据类型,int,long,float等都会完全复制,可以从以上的输出结果看出,所有复制对象的int输出都是0,而原对象输出的都是10;

总结:
原型模式的主要优点如下:
(1)当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
(2)原型模式提供了简化的创建模式,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的创建。
(3)可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。
原型模式的主要缺点如下:
(1)需要为每一个类创建一个克隆方法,而克隆方法位于类的内部,当对已有的功能进行修改时,就需要修改源代码,这违背了设计模式的六大原则中的“开闭原则”。
(2)深复制的实现机制很复杂,且当对象之间存在多重的嵌套引用时,为了实现深复制,每一层对象对应的类都必须支持深复制,这样实现一个类似这样的对象复制就显的尤为复杂。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!