Design pattern - the prototype model is simple and easy to understand

Posted by ctoshack on Sat, 18 Dec 2021 17:49:28 +0100

Prototype mode

1.0 definitions

Using an instance that has been created as a prototype, create a new object that is the same or similar to the prototype by copying the prototype object. Here, the prototype instance specifies the kind of object to create. Creating objects in this way is very efficient, and you don't need to know the details of object creation at all.

For example:

  1. The installation of Windows operating system is usually time-consuming, and the replication is much faster. There are many examples of replication in life, which are not listed here one by one.
  2. Copy and paste, which we often use, is this principle
  3. Scope of Spring bean @ Scope("prototype")

Prototype class diagram

  • For a prototype class, you only need to implement the Cloneable interface and duplicate the clone method. The clone method here can be changed to any name because the Cloneable interface is an empty interface. You can define the method name of the implementation class arbitrarily, such as cloneA or cloneB, because the focus here is super clone(), super Clone () calls the clone () method of the Object. In the Object class, clone () is native
  • Composition and roles involved
  1. Abstract prototype: declare an interface to clone itself;
  2. Concrete prototype class: implement an operation of cloning itself;
  3. Client: let a prototype clone itself to create a new object

2.0 benefits

  1. efficient;
  2. When creating complex objects, using prototype mode can simplify the creation process of objects;

3.0 disadvantages

  1. Clonable interface must be implemented;
  2. When objects have multi-layer reference nesting, it is more complex to realize deep cloning;
  3. When transforming a known class, the source code needs to be modified, which violates the opening and closing principle

4.0 clone type

  • Shallow cloning: after copying an object, the variables of the basic data type will be recreated, and the reference type still points to the original object.

    (for example, if the cloned object is modified, the prototype will also be modified because they point to the same reference address)

  • Deep copy: after copying an object, whether it is a basic data type or a reference type, it is recreated. In short, deep copy is completely copied, while shallow copy is not completely copied

    (for example, if the cloned object is modified, the prototype object will not be modified because they point to different reference addresses)

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-v3vq7qtf-1630229031675) (prototype model. assets/1630225748472.png)]

4.1 prototype mode - shallow cloning

Specific products
/**
 * <b>Function Description: shallow cloning, ` ConcretePrototype implements the operation of cloning itself < / b > < br >
 * @author newzhong
 * @version 1.0.0
 * @Note <b>Creation time: < / b > 2021-08-26 22:18
 * @since JDK 1.8
 */
@Data
public class ShallowClone implements Cloneable {
    private String userName;
    private Date birthDate;

    @Override
    public Object clone() throws CloneNotSupportedException {
        // ConcretePrototype implements an operation of cloning itself. Cloneable is equivalent to the abstract cloning interface native C++
        return super.clone();
    }
}
Client TEST
/**
 * <b>Function Description: < / b > < br >
 * @author newzhong
 * @version 1.0.0
 * @Note <b>Creation time: < / b > 2021-08-26 22:21
 * @since JDK 1.8
 */
public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        ShallowClone shallowClone = new ShallowClone();
        Date date = new Date();
        shallowClone.setBirthDate(date);
        shallowClone.setUserName("newzhong");

        System.out.println("----------------------");
        System.out.println(shallowClone.toString());

        ShallowClone clone = (ShallowClone) shallowClone.clone();
        System.out.println("--------------------");
        System.out.println(clone.toString());
        if (Objects.equals(shallowClone, clone)){
            System.out.println("Shallow cloned objects hashCode agreement");
        }
        // Modification; The reference pair prototype object is modified
        date.setTime(12345674);

        System.out.println("=================");
        System.out.println("================>v1"+shallowClone.toString());
        System.out.println("================>v1"+clone.toString());
    }
}

result:

Modification; The reference pair prototype object is modified

4.2 prototype mode - deep cloning

/**
 * <b>Function Description: < / b > < br >
 * @author newzhong
 * @version 1.0.0
 * @Note <b>Creation time: < / b > 2021-08-26 22:36
 * @since JDK 1.8
 */
@Data
public class DeepClone implements Cloneable{
    private String userName;
    private Date birthDate;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Object clone = super.clone();
        DeepClone d = (DeepClone) clone;
        // The properties of the object are also cloned
        d.birthDate = (Date) this.birthDate.clone();
        return clone;
    }
}
/**
 * <b>Function Description: < / b > < br >
 * @author newzhong
 * @version 1.0.0
 * @Note <b>Creation time: < / b > 2021-08-26 22:21
 * @since JDK 1.8
 */
public class DeepCloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        DeepClone deepClone = new DeepClone();
        Date date = new Date();
        deepClone.setBirthDate(date);
        deepClone.setUserName("newzhong");

        System.out.println("----------------------");
        System.out.println(deepClone.toString());

        DeepClone clone = (DeepClone) deepClone.clone();
        System.out.println("--------------------");
        System.out.println(clone.toString());
        if (Objects.equals(deepClone, clone)){
            System.out.println("Shallow cloned objects hashCode agreement");
        }
        date.setTime(12345674);

        System.out.println("=================");
        System.out.println("================>v1"+deepClone.toString());
        System.out.println("================>v1"+clone.toString());
    }
}

5.0 prototype mode summary

As a way to quickly create a large number of identical or similar objects, prototype pattern is widely used in software development. The copy (Ctrl + C) and paste (Ctrl + V) operations provided by many software are typical applications of prototype pattern

  1. Main advantages
  • When it is complex to create a new object instance, the prototype pattern can simplify the object creation process, and the creation efficiency of a new instance can be improved by copying an existing instance.
  • The extensibility is good. Because the Abstract prototype class is provided in the prototype mode, the Abstract prototype class can be programmed on the client, and the specific prototype class can be written in the configuration file. Adding or reducing product classes has no impact on the original system.
  • The prototype pattern provides a simplified creation structure. The factory method pattern often needs a factory hierarchy that is the same as the product class hierarchy, but the prototype pattern does not. The replication of products in the prototype pattern is realized through the cloning method encapsulated in the prototype class, and there is no need for a special factory class to create products.
  • You can use deep cloning to save the state of an object, and use prototype mode to copy an object and save its state for use when needed (such as restoring to a historical state), which can assist in the implementation of revocation.
  1. Main disadvantages
  • Each class needs to be equipped with a cloning method, and the cloning method is located inside a class. When transforming an existing class, the source code needs to be modified, which violates the "opening and closing principle".
  • When implementing deep cloning, you need to write more complex code, and when there are multiple nested references between objects, in order to implement deep cloning, the classes corresponding to each layer of objects must support deep cloning, which may be troublesome.
  1. Applicable scenario
  • The cost of creating new objects is large (such as initialization time, CPU resources or network resources). New objects can be obtained by copying existing objects in the prototype mode. If they are similar objects, their member variables can be modified slightly.
  • If the system wants to save the state of the object, and the state change of the object is very small, or the object itself occupies less memory, it can be realized by using prototype mode and memo mode.
    In case of multiple nested references, in order to realize deep cloning, the classes corresponding to each layer of objects must support deep cloning, which may be troublesome to implement.
  1. Applicable scenario
  • The cost of creating new objects is large (such as initialization time, CPU resources or network resources). New objects can be obtained by copying existing objects in the prototype mode. If they are similar objects, their member variables can be modified slightly.
  • If the system wants to save the state of the object, and the state change of the object is very small, or the object itself occupies less memory, it can be realized by using prototype mode and memo mode.
  • 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 composite states. It may be more convenient to get a new instance by copying the prototype object than to create a new instance by using the constructor.

Topics: Java Spring Design Pattern