A Brief Talk on prototype Prototype Model

Keywords: Programming Java Attribute JDK jvm

I. Introduction of Prototype Patterns

Prototype pattern is an object creation pattern. It uses the method of replicating prototype objects to create instances of objects. Instances created using prototype patterns have the same data as prototypes.

The characteristics of the prototype model:

1. Create the target object by the prototype object itself. That is to say, the action of object creation comes from the prototype object itself.

2. The target object is a clone of the prototype object. That is to say, the object created by the prototype pattern not only has the same structure as the prototype object, but also has the same value as the prototype object.

3. According to the different depth levels of cloning, there are shallow cloning and deep cloning.

1. Write a class that supports cloning

//Cloneable interface must be implemented if cloning is to be done
public class Person implements Cloneable{
    //An exception that does not support cloning may be thrown because the Cloneable interface is not implemented
    @Override
    protected Person clone(){
        try{
            return (Person) super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            return null;
        }
    }
}

2. Clones

public class MainClass {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = person1.clone();
    }
}

Such a clone is not identical to Person p2 = p1; for example, Person p2 = p1; it means creating a variable P2 in the stack and assigning the memory address of P1 to p2, actually referring to the same object. Cloning is to duplicate an identical object. The memory addresses of the two objects are different, but the structure and attribute values of the objects are identical.

This pattern is called prototype pattern. The core of this pattern is a clone() method. Through this method, Java provides a Cloneable interface to indicate that the object is copiable. Why is it called "tagging"? Turn over the help of JDK to see that Cloneable is a method that is not available. This interface is just a markup function. Only objects with this markup in JVM can be copied, so it is OK to override clone() method.

A note is added to the clone() method @Override Why can you override a class without inheriting it? In Java, the parent class of all classes is the Object class, and each class inherits this class by default, so it's very correct to use @Override. Although the prototype pattern is simple, there are still some considerations in using the prototype pattern, the clone method, in Java: class constructors are not executed when objects are copied. A class A that implements Cloneable and rewrites clone method has a parametric construct or a parametric construct B, generates an object S through new keyword, and then generates a new object T through S.clone(), then the constructor B will not be executed when the object is copied, and the constructor is not executed when the object is copied, which is theoretically speaking. It also makes sense that the Clone method of Object class copies from memory (specifically heap memory) in the form of binary stream and reallocates a memory block. It is also very normal that the constructor is not executed.

2. Deep cloning and shallow cloning

1. Shallow cloning

//Cloneable interface must be implemented if cloning is to be done
public class Person implements Cloneable{
    private String name;
    private String sex;
    private List<String> list;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public List<String> getList() {
        return list;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    //An exception that does not support cloning may be thrown because the Cloneable interface is not implemented
    @Override
    protected Person clone(){
        try{
            return (Person) super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            return null;
        }
    }
}

This is called shallow cloning. When there are reference objects in the cloned class (except for the packaging type such as String or Integer), the reference variables in the cloned class still store the previous memory address, that is to say, the cloned object is the same as the cloned object. In this way, two objects share a private variable, which can be changed by everyone. It is a very unsafe way to use it in real projects.

2. Deep copy

//Cloneable interface must be implemented if cloning is to be done
public class Person implements Cloneable{
    private String name;
    private String sex;
    private List<String> list;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public List<String> getList() {
        return list;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    //An exception that does not support cloning may be thrown because the Cloneable interface is not implemented
    @Override
    protected Person clone(){
        try{
            Person person = (Person) super.clone();
            List<String> newList = new ArrayList();
            
            for(String str : this.list){
                newList.add(str);
            }
            person.setList(newList);
            return person;
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            return null;
        }
    }
}

This completes the deep copy. The two objects are independent of each other and belong to separate objects.

Note: final type modified member variables cannot be copied in depth

3. Use scenarios of prototype patterns

  1. When creating an object, we want to inherit not only the basic structure of its base class, but also the data of the prototype object.
  2. It is hoped that the modification of the target object will not affect the existing prototype objects (in the case of deep cloning, it will not affect each other at all).
  3. Hiding the details of cloning operations, many times, cloning the object itself needs to involve the data details of the class itself.
  4. Class initialization requires a lot of resources, including data, hardware resources and so on.
  5. Producing an object through new requires very tedious data preparation or access rights, then prototype mode can be used.
  6. When an object needs to be accessed by other objects and each caller may need to modify its value, it is possible to consider using prototype mode to copy multiple objects for use by the caller. In practical projects, prototype patterns rarely appear alone, usually along with factory method patterns. An object is created by the clone method and then provided to the caller by the factory method. The prototype pattern first generates a class containing a large amount of common information, then copies out copies, corrects details and establishes a complete personality object.

Posted by desmortes on Wed, 18 Sep 2019 00:52:27 -0700