1. Introduction

  • Prototype pattern refers to using Prototype instances to specify the type of object to be created, and creating new objects by copying these prototypes
  • Prototyping is a creative design pattern that allows one object to create another customizable object without knowing the details of how to create it. Right
  • How it works: By passing a prototype object to the creation object, the creation object performs the creation by asking the prototype objects to copy themselves, called objects.clone ()

2. Examples of cloned sheep

Instance to describe

  • Create multiple instances of Sheep cloning

Create the Sheep instance using the new method

  • Sheep

    public class Sheep {
    
        private String name;
        private int age;
    
        public Sheep(String name,int age){
            this.name=name;
            this.age=age; }}Copy the code
  • Client

    public class Client {
        public static void main(String[] args) {
            Sheep sheep1 =new Sheep("name1".1);
            Sheep sheep2 =new Sheep("name2".2);
            Sheep sheep3 =new Sheep("name3".3); System.out.println(sheep1.hashCode()); System.out.println(sheep2.hashCode()); System.out.println(sheep3.hashCode()); }}Copy the code
  • The execution result

    460141958
    1163157884
    1956725890
    Copy the code
  • Traditional methods to analyze advantages: 1) better understand, easy to operation. 2) when creating a new object, always need to obtain the original properties of the object, if the created object is complex, low efficiency of 3) always need to initialize the object, rather than dynamically obtain the state of the object at runtime, inflexible

  • Using the Clone () method of Object and class in Java, this method can copy a Java Object, but the Java class that needs to implement clone must implement an interface Cloneable, which indicates that the class can be copied and has the ability to copy

Create the Sheep instance using the prototype pattern

  • Clone (); clone();

    public class Sheep implements Cloneable {
    
        private String name;
        private int age;
    
        public Sheep(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        protected Object clone(a) throws CloneNotSupportedException {
        	// Use the default clone method for shallow copies
            Sheep sheep = (Sheep) super.clone();
            returnsheep; }}Copy the code
  • Client

    public class Client {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Sheep sheep1 =new Sheep("name1".1); Sheep sheep2 = (Sheep) sheep1.clone(); Sheep sheep3 = (Sheep) sheep1.clone(); System.out.println(sheep1.hashCode()); System.out.println(sheep2.hashCode()); System.out.println(sheep3.hashCode()); }}Copy the code
  • The execution result

    460141958
    1163157884
    1956725890
    Copy the code

3. Shallow copy and deep copy

3.1 shallow copy

1) for a data type is based on the data type of member variables, shallow copy will pass directly to value, which is a copy of the attribute value for the new object type 2) is the reference data for the data type of member variables, such as a member variable is an array, a class of objects and so on, the shallow copy will be for reference, That is, only the reference value (memory address) of the member variable is copied to the new object. Because the member variable of both objects actually refers to the same instance. In this case, modifying the member variable in one object will affect the value of the member variable in the other object. 3) Shallow copies are implemented using the default Clone () method. 4) Clone sheep is implemented using shallow copies

3.2 deep copy

introduce

1) Copy the values of all member variables of the basic datatype of the object. 2) Allocate storage space for all member variables of the reference datatype, and copy the object referenced by each member variable of the reference datatype until the object is reachable to all objects. The clone method is overridden to implement deep copy. 4) The deep copy method is implemented through object serialization. This method requires the Serializable interface

Code implementation

Deep-copy mode 1: Rewrite the Clone method

  • DeepSheep implements Cloneable and overwrites the cloene() method

    public class DeepSheep implements Cloneable {
        private String address;
        private Sheep sheep;  // Reference type attributes
    
        public DeepSheep(String address, Sheep sheep) {
            this.address = address;
            this.sheep = sheep;
        }
    
        public Sheep getSheep(a) {
            return sheep;
        }
    
        public String getAddress(a) {
            return address;
        }
    
        @Override
        protected Object clone(a) throws CloneNotSupportedException {
            // Complete the clone of the base data type (attribute)
            DeepSheep deepSheep = (DeepSheep) super.clone();
            // Handle attributes of the reference type separately
            // Call clone() of sheep to clone the sheep
            deepSheep.sheep = (Sheep) sheep.clone();
            returndeepSheep; }}Copy the code
  • Client

    public class Client {	
    
        public static void main(String[] args) throws CloneNotSupportedException {
            DeepSheep deepSheep =new DeepSheep("address".new  Sheep("Primitive sheep".100)); DeepSheep deepSheepClone= (DeepSheep) deepSheep.clone(); deepSheepClone.getSheep().setName("Cloned sheep.");
            System.out.println(deepSheep.hashCode()+""+deepSheep.getAddress()+""+deepSheep.getSheep().toString()+""+deepSheep.getSheep().hashCode());
            System.out.println(deepSheepClone.hashCode()+""+deepSheepClone.getAddress()+""+deepSheepClone.getSheep().toString()+""+deepSheepClone.getSheep().hashCode()); }}Copy the code
  • The results

    460141958Address name: original sheep,age:100 1163157884
    1956725890Address name: Cloned sheep,age:100 356573597	
    Copy the code

Deep copy mode 2: Serialize objects

  • DeepSheep Both DeepSheep and Sheep need to implement the Serializable interface

    public class Sheep implements Serializable {}Copy the code
    public class DeepSheep implements  Serializable {
        private String address;
        private Sheep sheep;  // Reference type attributes
    
        public DeepSheep(String address, Sheep sheep) {
            this.address = address;
            this.sheep = sheep;
        }
    
        public Sheep getSheep(a) {
            return sheep;
        }
        
        public String getAddress(a) {
            return address;
        }
    
        /** * serialized deep copy **@return* /
        public DeepSheep deepClone(a) {
            // Create a stream object
            ByteArrayOutputStream bos = null;
            ObjectOutputStream oos = null;
            ByteArrayInputStream bis = null;
            ObjectInputStream ois = null;
            try {
                / / the serialization
                bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                oos.writeObject(this);  // Outputs the current object as a stream of objects
    
                // deserialize
                bis = new ByteArrayInputStream(bos.toByteArray());
                ois = new ObjectInputStream(bis);
                DeepSheep deepSheepCopy = (DeepSheep) ois.readObject();
                return deepSheepCopy;
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            } finally {
                try {
                    bos.close();
                    oos.close();
                    bis.close();
                    ois.close();
                } catch(IOException e) { e.printStackTrace(); }}}}Copy the code
  • Client

    public class Client {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            DeepSheep deepSheep = new DeepSheep("address".new Sheep("Primal Sheep 1".100));
            DeepSheep deepSheepClone = deepSheep.deepClone();
            deepSheepClone.getSheep().setName("Clone Sheep 2");
            System.out.println(deepSheep.hashCode() + "" + deepSheep.getAddress() + "" + deepSheep.getSheep().toString() + "" + deepSheep.getSheep().hashCode());
            System.out.println(deepSheepClone.hashCode() + "" + deepSheepClone.getAddress() + "" + deepSheepClone.getSheep().toString() + ""+ deepSheepClone.getSheep().hashCode()); }}Copy the code
  • The results

    1836019240Address name: original sheep1,age:100 1265094477
    363771819Address Name: Cloned sheep2,age:100 2065951873
    Copy the code

    Comparison between deep-copy mode 1 and mode 2: Mode 2 does not need to know how many attributes reference type attributes, which is more convenient

4. Matters and details

1) to create a new object is complicated, can use the archetypal pattern of simple object creation process, but also can improve the efficiency of 2) without having to initialize the object, but dynamically object runtime sends the status of the 3) if the original change (increase or decrease properties), the cloned object will have corresponding change, 5) Disadvantages: It is necessary to provide a clone method for each class, which is not difficult for the new class. However, when modifying the existing class, it needs to modify its source code, which violates the OCP principle