zoukankan      html  css  js  c++  java
  • 原型模式(Prototype Pattern)

    原型模式(Prototype Pattern)

    通过拷贝创建新的对象,调用者不用知道创建细节,不调用构造函数,是一种创建型模式,简而言之就是一个克隆一个对象,使用场景

    • 类初始化消耗资源过多
    • 构造函数比较复杂
    • 循环体中产生大量新的对象

    对于原型模式有两种写法,一种浅克隆(克隆对象使用的指向的同一个地址)一种深克隆(克隆对象的内容,地址不同),在【深度拷贝带随机指针的链表】 中我曾经提到。

    Shallow clone

    @Data
    @ToString
    public class ConcretePrototype implements Cloneable {
    
        private int age;
        private String name;
        private List<String> hobbies;
    
        @Override
        protected ConcretePrototype clone()  {
            try {
                return (ConcretePrototype) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
                return  null;
            }
        }
    }

    To test

    public class Client {
        public static void main(String[] args) {
            ConcretePrototype concretePrototype=new ConcretePrototype();
            concretePrototype.setAge(18);
            concretePrototype.setName("Glen");
            List<String> hobbies=new ArrayList<String>();
            hobbies.add("Girls");
            hobbies.add("Techniques");
            concretePrototype.setHobbies(hobbies);
    
            ConcretePrototype concretePrototype1=concretePrototype.clone();
            concretePrototype1.getHobbies().add("man");
            System.out.println(concretePrototype+"initial..");
            System.out.println(concretePrototype1+"cloned..");
            // They are different space of memory
            System.out.println(concretePrototype==concretePrototype1);
            // for primary data type can be pointed to different space of memory but specific type can not be (they remain point to the same space,such List)
            System.out.println(concretePrototype.getHobbies()==concretePrototype1.getHobbies());
        }
    }

    To explain:

    apparently,for instance, They are different spaces,but for specific, They are same space,so according conclusion,we get that it use shallow clone in basis of jdk for specific type,actually jdk just copy value of address of memory, like value of 'int boolean、char、float、double'  are saved in value of address of memory,but some specific types like List, in fact, their  value of address of memory are saved their value of addres,so just copy their value of addres cause same scenario of  value of addres.

     Deep clone

     method of serialization 

    @Data
    @ToString
    public class ConcretePrototype implements Cloneable,Serializable {
    
        private int age;
        private String name;
        private List<String> hobbies;
    
        ConcretePrototype deepClone()  {
            ByteOutputStream byteOutputStream=new ByteOutputStream();
            try {
                ObjectOutputStream objectOutput=new ObjectOutputStream(byteOutputStream);
                objectOutput.writeObject(this);
                ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteOutputStream.getBytes());
                ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
                return (ConcretePrototype) objectInputStream.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    To test

    public class Client {
        public static void main(String[] args) {
            ConcretePrototype concretePrototype=new ConcretePrototype();
            concretePrototype.setAge(18);
            concretePrototype.setName("Glen");
            List<String> hobbies=new ArrayList<String>();
            hobbies.add("Girls");
            hobbies.add("Techniques");
            concretePrototype.setHobbies(hobbies);
            // We just replace the method of our cloning
            ConcretePrototype concretePrototype1=concretePrototype.deepClone();
            concretePrototype1.getHobbies().add("man");
            System.out.println(concretePrototype+"initial..");
            System.out.println(concretePrototype1+"cloned..");
            System.out.println(concretePrototype==concretePrototype1);
            System.out.println(concretePrototype.getHobbies()==concretePrototype1.getHobbies());
        }
    }

     To explain

    We use  serialization to create the classess, do you remember that we had mentioned the method in singleton (use serialization  to destroy),so that we can not make a classess to be both singleton and  prototype!! do you remember that if we override 'readResolve' what is the result, Right! The 'java.io.ObjectInputStream#readObject0' will not create the new classess, so we must not override 'readResolve'

    Be applied into the souce of code

    java.util.ArrayList#clone

     java.util.HashMap#clone

     

     We find out that resouce of code above both Override the 'java.lang.Object#clone' so can we  Override that then add our logical code in it?definitely

        ConcretePrototype deepCloneHobbies() {
            try {
                ConcretePrototype clone = (ConcretePrototype) super.clone();
                clone.hobbies=(List)((ArrayList)clone.getHobbies()).clone();
                return clone;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

     Hi,we solve it perfectly,but if there are many specific type in the same class, do you want to do it more?so, personally, i think we use  method of serialization more complete!

    Sum up

    advantage

    • Be base on Binary stream to copy more  efficient than  to create a instance
    • To simplify process of creating a class

    disadvantage

      we must add a method of clone in each classess in order to with clone to create classess

     

  • 相关阅读:
    python中的os
    文件系统的简单操作
    文件与目录管理
    用户与用户组管理
    基础命令的操作
    linux开机流程
    ansible源码安装、普通用户实现批量控制
    python3中得数据类型
    判断一个字符串中得大写字母,小写字母,数字出现得次数
    Elasticsearch 如何安全加固
  • 原文地址:https://www.cnblogs.com/UpGx/p/14664144.html
Copyright © 2011-2022 走看看