Explain the Prototype Pattern of Java design pattern in detail

Keywords: Java Design Pattern Algorithm

Model introduction

Prototype Pattern is used to create duplicate objects while ensuring performance. This type of design pattern is a creation pattern, which provides the best way to create objects.

In a software system, it is sometimes necessary to create a certain type of object many times. In order to simplify the creation process, you can create only one object, and then copy multiple identical objects by cloning. This is the design idea of prototype pattern.

The basic working principle of prototype pattern is to pass a prototype object to the object to be created. The object to be created realizes the creation process by requesting the prototype object to copy the prototype itself.

Examples 👇

All the world knows. Sun Wukong's story of as like as two peas in the pilgrimage to the West. Sun Wukong can reproduce many of his own characters with his monkey's hair.

Monkey King's way of copying multiple bodies is called prototype pattern in the field of object-oriented design. As like as two peas, the object is copied from the original object, and the object is copied by the prototype.

In the software system, the creation process of some objects is complex and sometimes needs to be created frequently. The prototype pattern indicates the type of object to be created by giving a prototype object, and then creates more objects of the same type by copying the prototype object, which is the intention of the prototype pattern.

Pattern structure

The prototype pattern contains the following roles 👇

  1. Prototype (Abstract prototype class)

Abstract prototype class is an interface that defines methods to clone itself. It is the public parent class of all concrete prototype classes. It can be an abstract class or an interface.

  1. Concreteprototype (concrete prototype class)

The specific prototype class implements the specific cloning method, and returns one of its own cloned objects in the cloning method.

  1. Client (customer class)

The client class lets a prototype clone itself to create a new object. In the customer class, you only need to directly instantiate or create an object through factory methods, and then copy multiple identical objects by calling the cloning method of the object.

Model case

The cloning of prototype pattern can be divided into shallow cloning and deep cloning.

  • Shallow cloning: create a new object. The properties of the new object are exactly the same as the original object. For non basic type properties, it still points to the memory address of the object pointed to by the original property.

  • Deep clone: when a new object is created, other objects referenced in the attribute will also be cloned and no longer point to the original object address.

The following two examples of shallow cloning and deep cloning are used to further learn and understand the prototype pattern.

Case 1: mail copy of prototype pattern instance (shallow cloning)


  1. Abstract prototype class Object (no need to create)

Object is an abstract prototype class. In the Java language, all classes are subclasses of object. The clone() method is provided in object to create a prototype object. The concrete implementation of its clone() method is completed by the JVM, and users do not need to care when using it.

  1. Attachment class

In order to better illustrate the difference between shallow cloning and deep cloning, the Attachment class Attachment is introduced in this example. The mail class Email and Attachment class are combined associations. An Attachment class object is defined in the mail class as its member object.

package prototype;

/**
 * @author mengzhichao
 * @create 2021-11-10-22:20
 */
public class Attachment {

    public void download(){
        System.out.println("Download attachments");
    }
}
  1. Specific prototype class email (mail class)

Email class is a concrete prototype class and a subclass of Object class. In the Java language, only classes that implement the clonable interface can use the clone() method to copy, so the email class implements the clonable interface. Override the clone() method of Object in the email class, and return a cloned prototype Object by directly or indirectly calling the clone() method of Object. A member Object Attachment of type Attachment is defined in the email class.

package prototype;



/**
 * @author mengzhichao
 * @create 2021-11-10-22:18
 */
public class Email implements Cloneable {

    private Attachment attachment=null;

    public Email(){
        this.attachment=new Attachment();
    }

    @Override
    public Object clone(){
        Email clone =null;

        try {
            clone=(Email) super.clone();
        }catch (CloneNotSupportedException e){
            System.out.println("Clone failure!");
        }

        return clone;
    }

    public Attachment getAttachment(){
        return this.attachment;
    }

    public void display(){
        System.out.println("View mail");
    }

}
  1. Client test class Client

In the Client test class, compare whether the prototype object and the copied object are consistent, and compare whether the reference of its member object attachment is consistent.

package prototype;

/**
 * @author mengzhichao
 * @create 2021-11-10-22:29
 */
public class Client {
    public static void main(String[] args) {
        Email email,copyEmail;

        email=new Email();

        copyEmail= (Email) email.clone();

        System.out.println("email == copyEmail?");
        System.out.println(email == copyEmail);

        System.out.println("email.getAttachment() == copyEmail.getAttachment()?");
        System.out.println(email.getAttachment() == copyEmail.getAttachment());
    }
}

give the result as follows

  • It can be seen from the result that the result of the expression (email==copyEmail) is false, that is, the reference of the copied object is inconsistent with that of the prototype object, that is, there are two completely different objects in memory, one is the prototype object and the other is the object generated by cloning.
  • However, the result of the expression (email. Getattachment() = = copyemail. Getattachment()) is true, and the member objects of the two objects are the same, indicating that although the object itself is copied, its member objects are not copied in memory, and the prototype object and clone object maintain references to the same member object.

Case 2: email replication of prototype model instance (deep cloning)

Use deep cloning to copy messages, that is, copy attachments while copying messages.

  1. Attachment class

As a member object of the Email class, objects of Attachment type will also be written to the stream in shenkelong. Therefore, the Attachment class also needs to implement the Serializable interface.

package prototype2;

import java.io.Serializable;

/**
 * @author mengzhichao
 * @create 2021-11-10-22:20
 */
public class Attachment implements Serializable {

    public void download(){
        System.out.println("Download attachments");
    }
}
  1. Specific prototype class email (mail class)

As a specific prototype class, Email implements deep cloning and does not need to use the clone() method of Object, so it does not need to implement the clonable interface; Deep cloning can be realized by serialization (BOLD part in the code). Since the Email type Object is to be written to the stream, the Email class needs to implement the Serializable interface.

package prototype2;



import java.io.*;

/**
 * @author mengzhichao
 * @create 2021-11-10-22:18
 */
public class Email implements Serializable {

    private Attachment attachment=null;

    public Email(){
        this.attachment=new Attachment();
    }


    public Object deepClone() throws IOException,ClassNotFoundException, OptionalDataException{
        //Write object to stream
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos =new ObjectOutputStream(bao);
        oos.writeObject(this);

        //Take the object out of the stream
        ByteArrayInputStream bis =new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois =new ObjectInputStream(bis);
        return (ois.readObject());
    }


    public Attachment getAttachment(){
        return this.attachment;
    }

    public void display(){
        System.out.println("View mail");
    }
}
  1. Client test class Client

In the Client test class, we still compare whether the prototype object and the copy object after deep cloning are consistent, and compare whether the reference of its member object attachment is consistent.

package prototype2;

/**
 * @author mengzhichao
 * @create 2021-11-11-22:28
 */
public class Client {

    public static void main(String[] args) {
        Email email,copyEmail = null;
        email=new Email();

        try {
            copyEmail = (Email) email.deepClone();
        }catch (Exception e){
            e.printStackTrace();
        }

        System.out.println("email==copyEmail?");
        System.out.println(email==copyEmail);

        System.out.println("email.getAttachment()==copyEmail.getAttachment()?");
        System.out.println(email.getAttachment()==copyEmail.getAttachment());
    }
}

It can be seen from the result that the result of the expression (email==copyEmail) is false, that is, the reference of the copied object is inconsistent with that of the prototype object, the result of the expression (email.getAttachment()==copyEmail.getAttachment()) is also false, and the reference of the prototype object and the clone object to the member object is different, indicating that its member object is also copied.

Model summary

  • Advantages and disadvantages: the biggest advantage of prototype mode is that it can quickly create many identical or similar objects, simplify the creation process of objects, and save some intermediate states of objects.
    The disadvantage is that each class needs to be equipped with a cloning method, so it is troublesome to transform the existing classes, modify their source code, and write more complex code when implementing deep cloning.

  • Applicable to: the cost of creating new objects is large. New objects can be obtained by copying existing objects in prototype mode. The system needs to save the state of the object, and the state change of the object is very small. It is necessary to avoid using hierarchical factory classes to create hierarchical objects, and the instance object of the class has only one or few combined states. It may be more convenient to obtain a new instance by copying the prototype object than to create a new instance by using the constructor.

Expand content

Prototype pattern with prototype Manager

  • An improved form of prototype pattern is the prototype pattern with prototype manager.

The prototype manager role creates objects of specific prototype classes and records each created object. The role of the prototype manager is similar to that of a factory. A collection is defined to store prototype objects. If a clone of an object is needed, it can be obtained by copying the corresponding prototype objects in the collection. The Abstract prototype class is programmed in the prototype manager for extension.

The following uses code simulation to demonstrate the implementation of a color prototype manager.

  1. Abstract prototype class MyColor
package prototypemanager;

/**
 * @author mengzhichao
 * @create 2021-11-14-10:30
 */
public interface MyColor extends Cloneable {

    public Object clone();

    public void display();
}
  1. Concrete prototype class Red
package prototypemanager;

/**
 * @author mengzhichao
 * @create 2021-11-14-10:32
 */
public class Red implements MyColor {
    @Override
    public Object clone() {
        Red r=null;
        try {
            r = (Red) super.clone();
        }catch (Exception e){

        }
        return r;
    }

    @Override
    public void display() {
        System.out.println("This is Red");
    }
}
  1. Specific prototype class Blue
package prototypemanager;

/**
 * @author mengzhichao
 * @create 2021-11-14-10:36
 */
public class Blue implements MyColor {
    @Override
    public Object clone() {
        Blue b=null;
        try {
            b = (Blue) super.clone();
        }catch (Exception e){

        }
        return b;
    }
    @Override
    public void display() {
        System.out.println("This is Blue");
    }
}
  1. Prototype manager class PrototypeManager
package prototypemanager;

import java.util.Hashtable;

/**
 * @author mengzhichao
 * @create 2021-11-14-10:37
 */
public class PrototypeManager {

    private Hashtable ht =new Hashtable();

    public PrototypeManager() {
        ht.put("red",new Red());
        ht.put("blue",new Blue());
    }

    public void addColor(String key,MyColor obj){
        ht.put(key,obj);
    }

    public MyColor getColor(String key){
        return (MyColor) ((MyColor)ht.get(key)).clone();
    }

}
  1. Client test class Client
package prototypemanager;

/**
 * @author mengzhichao
 * @create 2021-11-14-10:47
 */
public class Client {

    public static void main(String[] args) {
        PrototypeManager pm =new PrototypeManager();

        MyColor obj1=pm.getColor("red");
        obj1.display();

        MyColor obj2=pm.getColor("red");
        obj2.display();

        System.out.println(obj1==obj2);

    }
}

The operation results are as follows

  • A collection of Hashtable types is defined in the PrototypeManager. The prototype object is stored by "Key value pair". The client can obtain the clone object of the corresponding prototype object through the Key. The PrototypeManager class provides factory methods to return a cloned object.

More wonderful articles visit: https://blog.csdn.net/weixin_45692705?spm=1011.2124.3001.5343

Pay attention to the official account below. Thank you! 👇

Posted by stig1 on Wed, 01 Dec 2021 04:50:46 -0800