• 设计模式之--原型模式


    原型模式

    原型实例指定创建对象的种类,并且通过复制这些原型创建新对象。

    使用场景:

    1. 类初始化消耗资源比较多。
    2. 使用new生成一个对象需要非常繁琐的过程。
    3. 构造函数比较复杂。
    4. 在循环体中产生大量对象。

    浅克隆

    浅克隆只是完整复制了值类型数据,没有赋值引用对象。换言之,所有的引用对象仍然指向原来的对象。

    eg:

    /**
     * 原型接口
     */
    public interface Prototype {
    
        Prototype clone();
    }
    
    
    /**
     * 需要克隆的类 实现原型接口类
     */
    @Data
    public class ConcretePrototypeA  implements Prototype{
    
    private String name;
    private Integer age;
    private List<String> hobbies;
    
        @Override
        public ConcretePrototypeA clone() {
            ConcretePrototypeA concretePrototypeA=new ConcretePrototypeA();
            concretePrototypeA.setAge(this.age);
            concretePrototypeA.setHobbies(this.hobbies);
            concretePrototypeA.setName(this.name);
            return concretePrototypeA;
        }
    }
    
    /**
     * 类
     */
    public class Client {
        private Prototype prototype;
    
        public Client(){}
        public Client (Prototype prototype){
            this.prototype =prototype;
        }
    
        public Prototype startClone(Prototype concretePrototypeA){
            return concretePrototypeA.clone();
        }
    }
    
    /**
     * 测试类
     */
    public class qianCloneTest {
    
        public static void main(String[] args) {
    
            ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
            concretePrototypeA.setName("小明");
            concretePrototypeA.setAge(33);
            ArrayList<String> list = new ArrayList<>();
            list.add("排球");
            concretePrototypeA.setHobbies(list);
            System.out.println( "new出来的 ==== 》 "+concretePrototypeA);
    
    
            //clone出来---浅克隆  ,hobbies的引用地址是相同的,意味着复制的不是值,而是引用的地址
    //        浅克隆只是完整复制了值类型数据,没有赋值引用对象。换言之,所有的引用对象仍然指向原来的对象
            Client client = new Client(concretePrototypeA);
            ConcretePrototypeA prototypeClone =(ConcretePrototypeA) client.startClone(concretePrototypeA);
            System.out.println("浅克隆====》"+prototypeClone);
    
            System.out.println("克隆的对象类型的内存地址"+prototypeClone.getHobbies());
            System.out.println("创建的的对象类型的内存地址"+concretePrototypeA.getHobbies());
            System.out.println("对象类型的内存地址比较"+ (prototypeClone.getHobbies() == concretePrototypeA.getHobbies()));
    
        }
    }
    
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    测试结果

    new出来的 ==== 》 ConcretePrototypeA(name=小明, age=33, hobbies=[排球])
    浅克隆====》ConcretePrototypeA(name=小明, age=33, hobbies=[排球])
    克隆的对象类型的内存地址[排球]
    创建的的对象类型的内存地址[排球]
    对象类型的内存地址比较true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    深克隆

    深克隆会将类的值类型,引用类型数据完全copy一份。会产生新的内存地址。

    eg:

    /**
     * 实体类--monkey
     */
    @Data
    public class Monkey {
        private Integer  height;
    
        private Integer weight;
    
        private Date   birthday;
    
    }
    
    /**
     * 金箍棒类--附属属性
     */
    @Data
    public class Jingubang  implements Serializable {
        private float h=1000;
        private float d=10;
    
        public void  small(){
            this.h/=2;
            this.d/=2;
        }
        public void  big(){
            this.h*=2;
            this.d*=2;
        }
    
    }
    
    /**
     * 齐天大圣类
     */
    @Data
    public class QiTianDaSheng extends Monkey implements Serializable ,Cloneable {
    
        private Jingubang jingubang;
    
        QiTianDaSheng(){
            //初始化数据
            this.setBirthday(new Date());
            this.setJingubang(new Jingubang());
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return this.deepClone();
        }
    
    
        private Object  deepClone(){
            try{
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(this);
    
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bis);
    
                QiTianDaSheng copy = (QiTianDaSheng)ois.readObject();
                copy.setBirthday(new Date());
                return copy;
    
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
    
        //浅克隆
        public QiTianDaSheng shallowClone(QiTianDaSheng target){
            QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
            qiTianDaSheng.setBirthday(new Date());
            qiTianDaSheng.setJingubang(target.getJingubang());
            qiTianDaSheng.setHeight(target.getHeight());
            qiTianDaSheng.setWeight(target.getWeight());
            return qiTianDaSheng;
        }
    }
    
    
    /**
     * 测试类
     */
    public class DeepCloneTest {
        public static void main(String[] args) {
            QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
            try {
                QiTianDaSheng clone = (QiTianDaSheng)qiTianDaSheng.clone();
                System.out.println("深clone:"+(qiTianDaSheng.getJingubang()==clone.getJingubang()));
    
            }catch (Exception e){
                e.printStackTrace();
            }
    
            QiTianDaSheng q = new QiTianDaSheng();
            QiTianDaSheng n = q.shallowClone(q);
            System.out.println("浅克隆:"+(q.getJingubang()==n.getJingubang()));
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    测试结果

    深clone:false
    浅克隆:true
    
    • 1
    • 2

    总结:

    deepClone方法利用序列化实现深度克隆

    把对象写到流里的过程是序列化(Serialization)过程;而把对象从流中读出来的过程则叫反序列化(Deserialization)过程。应当指出的是,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。

    在Java语言里深度克隆一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的拷贝)写到一个流里(序列化),再从流里读回来(反序列化),便可以重建对象。

    这样做的前提就是对象以及对象内部所有引用到的对象都是可序列化的,否则,就需要仔细考察那些不可序列化的对象可否设成transient,从而将之排除在复制过程之外。

    浅度克隆显然比深度克隆更容易实现,因为Java语言的所有类都会继承一个clone()方法,而这个clone()方法所做的正是浅度克隆。

    Java 提供了一个 Cloneable 接口来标示这个对象是可拷贝的,为什么说是“标示”呢?翻开 JDK 的帮助看看 Cloneable 是一个方法都没有的接口,这个接口只是一个标记作用,在 JVM 中具有这个标记的对象才有可能被拷贝,覆盖clone()方法就可以了。

  • 相关阅读:
    C#构造函数
    springmvc-controller&视图层配置&SpringMVC处理请求的流程
    Java Web实现用户登录功能
    URL、域名和网址的区别
    方法调用过程
    【MybatisPlus】MP的分页查询、多条件查询以及查询过程中解决null的空值判定
    工作笔记.
    【深度学习】实验6布置:图像自然语言描述生成(让计算机“看图说话”)
    使用Keras代码解决二分类问题
    Z-DArg-GR-pNA,113711-77-6
  • 原文地址:https://blog.csdn.net/qq_51347907/article/details/126312627