Prototype mode of 23 design modes

Posted by jaybird84404 on Tue, 25 Jan 2022 15:13:40 +0100

Prototype mode

Cloning sheep:

Now there is a sheep tom, whose name is tom, age is 1, and color is white. Please write a program to create 10 sheep with exactly the same attributes as tom's sheep

Traditional ways to solve the problem of cloned sheep

  1. Train of thought analysis (illustration)

  2.  

  3. Code demonstration

Sheet class:

package com.atguigu.prototype;

public class Sheep {
    private String name;
    private int age;
    private String color;
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
    }
    
    
}

Client class:

package com.atguigu.prototype;

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Traditional methods
        Sheep sheep = new Sheep("tom", 1, "white");
        
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        //....
        
        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
        //...
    }

}

Advantages and disadvantages of traditional methods

  1. The advantages are easy to understand, simple and easy to operate.

  1. When creating a new object, you always need to retrieve the properties of the original object. If the created object is complex, the efficiency is low

  1. It is always necessary to reinitialize the object instead of dynamically obtaining the running state of the object, which is not flexible enough

  1. Analysis of improvement ideas

Idea: the Object class in Java is the root class of all classes. The Object class provides a clone() method, which can copy a Java Object, but the Java class that needs to implement clone must implement an interface clonable, which indicates that the class can copy and has the ability to copy = > prototype mode

Basic introduction to prototype mode

  1. Prototype pattern refers to specifying the type of objects to be created with prototype instances, and creating new objects by copying these prototypes

  1. Prototype pattern is a creative design pattern that allows one object to create another customizable object without knowing the details of how to create it

  1. The working principle is: by passing a prototype object to the object to be created, the object to be created is created by requesting the prototype object to copy itself, that is, the object clone()

  1. Image understanding: Sun Dasheng pulls out monkey hair and turns into other sun Dasheng

Schematic structure diagram of prototype pattern uml class diagram

Description of schematic structure diagram:

  1. Prototype: prototype class, which declares an interface to clone itself

  1. ConcretePrototype: a concrete prototype class that implements the operation of cloning itself

  1. Client: let a prototype object clone itself to create a new object (with the same properties)

Prototype pattern solves the problem of cloned sheep

Using prototype mode to improve the traditional way, so that the program has higher efficiency and scalability. This method is a shallow copy.

Code:

Sheet class:

package com.atguigu.prototype.improve;




public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    private String address = "Mongolian sheep";
    public Sheep friend; //Is the object, How will cloning be handled
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    
    
    
    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
    }
    //Clone the instance, using the default clone Method to complete
    @Override
    protected Object clone()  {
        
        Sheep sheep = null;
        try {
            sheep = (Sheep)super.clone();
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }
        // TODO Auto-generated method stub
        return sheep;
    }
    
    
}

Client class:

package com.atguigu.prototype.improve;



public class Client {

    public static void main(String[] args) {
        System.out.println("Prototype mode completes the creation of objects");
        // TODO Auto-generated method stub
        Sheep sheep = new Sheep("tom", 1, "white");
        
        sheep.friend = new Sheep("jack", 2, "black");
        
        Sheep sheep2 = (Sheep)sheep.clone(); //clone
        Sheep sheep3 = (Sheep)sheep.clone(); //clone
        Sheep sheep4 = (Sheep)sheep.clone(); //clone
        Sheep sheep5 = (Sheep)sheep.clone(); //clone
        
        System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
        System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
        System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
        System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());
    }

}

Introduction to shallow copy

  1. For member variables whose data type is the basic data type, shallow copy will directly transfer the value, that is, copy the attribute value to a new object.

  1. For a member variable whose data type is a reference data type, for example, if the member variable is an array or a class object, the shallow copy will be passed by reference, that is, just copy the reference value (memory address) of the member variable to the new object. Because in fact, the member variable of both objects points to the same instance. In this case, modifying the member variable in one object will affect the value of the member variable in another object

  1. In front of us, cloning sheep is a shallow copy

  1. Shallow copy is implemented using the default clone() method

    sheep = (Sheep) super.clone();

Introduction to deep copy

  1. Copy the member variable values of all basic data types of the object

  1. Apply for storage space for all member variables of reference data type, and copy the object referenced by each member variable of reference data type until all objects reached by the object. That is to say, to make a deep copy of an object, you need to copy the whole object

  1. Deep copy implementation method 1: rewrite the clone method to implement deep copy

  1. Deep copy implementation method 2: realize deep copy through object serialization (recommended)

Deep copy application instance

  1. Implement deep copy by rewriting clone method

  1. Deep copy using serialization

  1. Code demonstration

DeepCloneableTarget class:

package com.atguigu.prototype.deepclone;

import java.io.Serializable;

public class DeepCloneableTarget implements Serializable, Cloneable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private String cloneName;

    private String cloneClass;

    //constructor 
    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }

    //Because the properties of this class are String , So we use the default here clone Just finish
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

DeepProtoType class:

package com.atguigu.prototype.deepclone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepProtoType implements Serializable, Cloneable{
    
    public String name; //String attribute
    public DeepCloneableTarget deepCloneableTarget;// reference type
    public DeepProtoType() {
        super();
    }
    
    
    //Deep copy - Mode 1 use clone method
    @Override
    protected Object clone() throws CloneNotSupportedException {
        
        Object deep = null;
        //Here is the basic data type(attribute)and String Clone of
        deep = super.clone(); 
        //The properties of reference types are processed separately
        DeepProtoType deepProtoType = (DeepProtoType)deep;
        deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();
        
        // TODO Auto-generated method stub
        return deepProtoType;
    }
    
    //Deep copy - Method 2 is implemented through object serialization (recommend)
    
    public Object deepClone() {
        
        //Create flow object
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        
        try {
            
            //serialize
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //Currently, this object is output as an object stream
            
            //Deserialization
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType)ois.readObject();
            
            return copyObj;
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //Close flow
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }
        }
        
    }
    
}

Client class:

package com.atguigu.prototype.deepclone;

public class Client {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        DeepProtoType p = new DeepProtoType();
        p.name = "Song Jiang";
        p.deepCloneableTarget = new DeepCloneableTarget("Daniel", "Calf");
        
        //Method 1: complete deep copy
        
//        DeepProtoType p2 = (DeepProtoType) p.clone();
//        
//        System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
//        System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
    
        //Method 2: complete deep copy
        DeepProtoType p2 = (DeepProtoType) p.deepClone();
        
        System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
        System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
    
    }

}

Precautions and details of prototype pattern

  1. When creating a new object is complex, you can use the prototype pattern to simplify the object creation process and improve efficiency

  1. Instead of reinitializing the object, it dynamically obtains the running state of the object

  1. If the original object changes (increase or decrease attributes), other cloned objects will also change accordingly without modifying the code

  1. The implementation of deep cloning may require more complex code

  1. Disadvantages: each class needs to be equipped with a cloning method, which is not very difficult for new classes, but when transforming existing classes, you need to modify their source code, which violates the ocp principle. Please pay attention to this