zoukankan      html  css  js  c++  java
  • 设计模式之原型模式

    原型模式,即Prototype,是指创建新对象的时候,根据现有的一个原型来创建。

    1. 原型模式

    原型模式(Prototype)比较类似于复制粘贴的思想,它可以首先创建一个实例,然后通过这个实例进行新对象的创建。在 Java 中,最典型的就是 Object 类的 clone 方法。

    但编码中这个方法很少用,我们在代理模式提到的 prototype,并不是通过 clone 实现的,而是使用了更复杂的反射技术。

    一个比较重要的原因就是 clone 如果只拷贝当前层次的对象,实现的只是浅拷贝。在现实情况下,对象往往会非常复杂,想要实现深拷贝的话,需要在 clone 方法里做大量的编码,远远不如调用 new 方法方便。

    实现深拷贝,还有序列化等手段,比如实现 Serializable 接口,或者把对象转化成 JSON。

    所以,在现实情况下,原型模式变成了一种思想,而不是加快对象创建速度的工具。

    使用的时候,因为clone()的方法签名是定义在Object中,返回类型也是Object,所以要强制转型,比较麻烦:

    Student student = new Student();
    student.setName("li");
    Student student2 = (Student)student.clone();
    
    System.out.print(student==student2); //  false
    

    实际上,使用原型模式更好的方式是定义一个copy()方法,返回明确的类型:

    public class Student {
        private int id;
        private String name;
        private int score;
    
        public Student copy() {
            Student std = new Student();
            std.id = this.id;
            std.name = this.name;
            std.score = this.score;
            return std;
        }
    }
    

    原型模式应用不是很广泛,因为很多实例会持有类似文件、Socket这样的资源,而这些资源是无法复制给另一个对象共享的,只有存储简单类型的“值”对象可以复制。

    2. Java中的浅拷贝和深拷贝

    2.1 引用拷贝

    创建一个指向对象的引用变量的拷贝。

    Teacher teacher = new Teacher("Taylor",26);
    Teacher otherteacher = teacher;
    System.out.println(teacher);
    System.out.println(otherteacher);
    
    结果:
    blog.Teacher@355da254
    blog.Teacher@355da254
    

    结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacher和otherteacher的只是引用而已,他们都指向了一个相同的对象Teacher(“Taylor”,26)。 这就叫做引用拷贝。

    2.2 对象拷贝

    创建对象本身的一个副本。

    Teacher teacher = new Teacher("Swift",26);
    Teacher otherteacher = (Teacher)teacher.clone();
    System.out.println(teacher);
    System.out.println(otherteacher);
    
    结果
    blog.Teacher@355da254
    blog.Teacher@4dc63996
    

    结果分析:由输出结果可以看出,它们的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量,这就叫做对象拷贝。

    深拷贝和浅拷贝都是对象拷贝

    2.3 浅拷贝

    被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。"里面的对象“会在原来的对象和它的副本之间共享。

    简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象

    2.4 深拷贝

    深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

    简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍

    2.5 通过序列化进行深拷贝

    public Object deepClone() throws Exception {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
    
            oos.writeObject(this);
    
            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
    
            return ois.readObject();
        }
    

    References

  • 相关阅读:
    接口和抽象类
    TSQL向自增字段中插入值
    字符串驻留备忘
    SQL Like中的逗号分隔符
    TSQL的一点小备忘
    ADO.NET与ADO
    JavaScript Office文档在线编辑备忘
    位运算练习:求多数的大数、二进制数中1的个数
    Vimeo反反复复地重生死亡。
    海底浓烟,低分辨率测试。
  • 原文地址:https://www.cnblogs.com/wei57960/p/14691176.html
Copyright © 2011-2022 走看看