• Java设计模式-创建型模式-原型模式


    原型模式

    要求:以一个已经创建的对象为原型,复制一个新的对象

    使用场景:

    创建对象的成本比较大的时候(如从耗时较长的计算或者从查询耗时长的RPC接口获取数据),直接拷贝已有对象,而不是每次耗时创建对象。

    原型模式分为两种,浅拷贝深拷贝

    • 浅拷贝:克隆对象所有变量的值与原型对象完全一致,引用数据类型(除String类型)的地址也一致
    • 深拷贝:克隆对象所有变量的内容与原型对象完全一致,但引用数据类型的地址不一致

    下面以学生和奖状的例子 讲述深拷贝和浅拷贝

    浅拷贝

    Object类中提供了clone()方法来实现浅克隆,但是需要实现Cloneable接口,代码如下:

    // 奖状类
    class Citation implements Cloneable {
        private String name; // 注意,String为不可变类
    
        public Citation(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
     
        public String getName() {
            return this.name;
        }
     
        public void show() {
            System.out.println(name);
        }
     
        @Override
        protected Citation clone() throws CloneNotSupportedException {
            return (Citation) super.clone();
        }
    
        @Override
        public String toString() {
            return "Citation{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    测试代码:

    /**
     * 浅拷贝
     * 复制一个奖状类
     */
    @Test
    public void ShallowCopy() throws CloneNotSupportedException {
        Citation citation = new Citation("三好学生");
        Citation clone = citation.clone();
        citation.show();
        clone.show();
        System.out.println(clone == citation);
    }
    输出:
    三好学生
    优秀学生
    false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    上述奖状类,只有一个String 类型,没有其他引用类型,可以使用clone()方法进行浅拷贝

    但对于有其他引用属性的对象,例如,一个学生对象有一个奖状属性,这时如果还使用浅拷贝,复制的学生对象,引用的奖状就是同一个(地址相同),修改奖状属性,就会导致所有拷贝的学生的奖状信息都跟着改变,这显然不是我们想要的

    这时就需要使用深拷贝完成复制,代码如下:

    深拷贝

    public class Student implements Cloneable{
        private String name;
    
        private Citation citation;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setCitation(Citation citation) {
            this.citation = citation;
        }
    
        public Citation getCitation(){
            return citation;
        }
        /**
         * 深拷贝
         * @return
         * @throws CloneNotSupportedException
         */
        @Override
        protected Student clone() throws CloneNotSupportedException {
            Student clone = (Student) super.clone();
            Citation citation = this.citation.clone();
            clone.setCitation(citation);
            return clone;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", citation=" + citation +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    测试代码:

    /**
     * 深拷贝
     * 复制一个学生改个名
     */
    @Test
    public void DeepCopy() throws CloneNotSupportedException {
        Student student = new Student();
        student.setName("张三");
        student.setCitation(new Citation("三好学生"));
    
        Student clone = student.clone();
        clone.setName("李四");
        clone.getCitation().setName("优秀学生");
        System.out.println(student);
        System.out.println(clone);
        System.out.println(student == clone);
    }
    
    输出:
    Student{name='张三', citation=Citation{name='三好学生'}}
    Student{name='李四', citation=Citation{name='优秀学生'}}
    false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    原型模式的本质就是clone,可以解决构建复杂对象的资源消耗问题,能再某些场景中提升构建对象的效率;还有一个重要的用途就是保护性拷贝,可以通过返回一个拷贝对象的形式,实现只读的限制。

  • 相关阅读:
    主应用窗口
    学生免费申请IDEA使用流程
    新电脑Mac安装前端环境,未完待续~
    微服务之流控、容错组件sentinel
    ModelAndView类简介说明
    利用大模型反馈故障的解决方案
    如何实现模拟量信号远距离无线传输?
    Linux入门基本操作3
    苹果mac笔记本部分按键失灵怎么回事?5连option键即可解决
    java基础选择题--17(包含全面)
  • 原文地址:https://blog.csdn.net/ren9436/article/details/134341294