(Prototype Pattern)

(Prototype Pattern)

Creating a new object by copying, the caller does not need to know the creation details, does not call the constructor, is a creation pattern, in short, it is a clone of an object, use the scene

  • Class initialization consumes too many resources
  • Constructors are complex
  • A large number of new objects are generated in the loop

There are two ways to write the prototype pattern, a shallow clone (the cloned object uses the same address) and a deep clone (the content of the cloned object is different),I mentioned this in [deep copy linked list with random pointers].

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

 

 

 

 

posted @ 2021-04-15 19:46  UpGx  阅读(75)  评论(0)    收藏  举报