Learning of Prototype Patterns of Java23 Design Patterns

Source link (Gitee code cloud): https://gitee.com/oldou/javadesignpatterns
Here is the source code of Java23 design patterns and blog tutorials that I have compiled. The blog tutorial introduces various implementations of Java23 design patterns. And application scenarios, it is very suitable for learning and improving our design thinking. If it is helpful to everyone, please remember to star and give the author some spiritual support. Your star is the motivation for me to write a better blog. Thank you.

Prototype

Introduction

The prototype pattern (Prototype Pattern) is used to create repetitive objects while ensuring performance. This type of design pattern belongs to the creation pattern, which provides the best way to create objects.

This model implements a prototype interface, which is used to create a clone of the current object. This mode is used when the cost of directly creating an object is relatively high. For example, an object needs to be created after a costly database operation. We can cache the object, return its clone on the next request, and update the database when needed to reduce database calls.

  • Generating an object through new requires very tedious data preparation or access permissions, so you can use the prototype mode.
  • It is the cloning technology in java, which uses an object as a prototype to copy a new object. Obviously, the new object has the characteristics of the prototype object
  • The advantages are: high efficiency (direct cloning, avoiding re-execution of the construction process steps).
  • Cloning is similar to new, but different from new. New creates new object properties with default values. The property values ​​of the cloned object are exactly the same as the prototype object. And changes to the cloned new object will not affect the prototype object. Then, modify the value of the cloned object.

Prototype mode implementation

  • By implementing the Cloneable interface and rewriting the clone method
  • The most difficult part to implement in Prototype mode is the memory copy operation. Fortunately, the clone() method is provided in Java to do most of the things for us.

classification

The core of the prototype pattern is to copy objects, so what content can we copy an object instance? It is necessary to distinguish between deep copy and shallow copy.

(1) Shallow copy: We only copy the basic data types (8 types) in the object, and will not copy the array, container, reference object, etc.

  • The problems of shallow cloning
    All variables of the copied object contain the same value as the original object, and all references to other objects still point to the original object.

(2) Deep copy: not only can copy basic data types, but also those arrays, containers, reference objects, etc.;

  • How to realize
    deep cloning ? Deep cloning points the referenced variable to the copied new object instead of the original referenced object.
    Deep cloning: Let the properties in the class that have implemented the Clonable interface also implement the Clonable interface;
    basic data types and String can automatically implement deep cloning (copy of values).

Below we use code to implement shallow clone and deep clone respectively.

The realization of shallow clone

Step 1: Define the prototype class

/** 原型模式(浅克隆)
 * 第一步:实现 Cloneable 接口
 * 第二步: 重写一个方法---clone()
 */
public class Video implements Cloneable {
    
     //视频的原型

    private String name;//视频的名字
    private Date createTime;//视频的发布日期

    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        return super.clone();
    }

    public Video() {
    
    
    }
    public Video(String name, Date createTime) {
    
    
        this.name = name;
        this.createTime = createTime;
    }
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public Date getCreateTime() {
    
    
        return createTime;
    }
    public void setCreateTime(Date createTime) {
    
    
        this.createTime = createTime;
    }
    @Override
    public String toString() {
    
    
        return "Video{" +
                "name='" + name + '\'' +
                ", createTime=" + createTime +
                '}';
    }
}

Client:

/**
 * 客户端:克隆别人的视频
 */
public class Client {
    
    

    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        //首先创建一个原型对象
        Date date = new Date();
        Video v1 = new Video("Java入坑指南",date);

        System.out.println("v1的信息---->"+v1);
        System.out.println("v1的HashCode为:"+v1.hashCode());

        //通过克隆v1创建出一个v2对象
        Video v2 = (Video)v1.clone();
        System.out.println("v2的信息---->"+v2);
        System.out.println("v2的HashCode为:"+v2.hashCode());

    }
}

First, we clone v1 out of v2 through the Object cloning method. At the same time, comparing v1 and v2,
Insert picture description here
we can see that the basic information is exactly the same, but the HashCode is different, which can indicate that these are two different objects, but such a clone There is a problem. Our above code has a total of three objects, v1, v2 and date objects. The relationship diagram is as follows:
Insert picture description here
we use the above method to clone is called shallow clone, and the cloned v2 and v1 point to the same date, below Let's test it through the code:

//首先创建一个原型对象
Date date = new Date();
Video v1 = new Video("Java入坑指南",date);
Video v2 = (Video)v1.clone();
System.out.println("v1的信息---->"+v1);
System.out.println("v2的信息---->"+v2);

System.out.println("-------------------------------");
date.setTime(22322121);//随意修改一下时间,说明时间是改变了
System.out.println("v1的信息---->"+v1);
System.out.println("v2的信息---->"+v2);

Output:
Insert picture description here
It can be proved from the output result that v1 and v2 point to the same value date at the same time, which means that we just copied all the object values, and also includes the object reference, so it points to the same date. , This is the problem of shallow cloning. But this is not the result we want, the result we want is to have our own references after being cloned.

Implementation of deep cloning

As shown in the figure below: Insert picture description here
the object we want to clone has its own Date object. When changing the Date of v1, it will not change the Date of v2. To achieve deep cloning, we need to modify the clone() method to clone the object at the same time The properties of the object are also cloned.
Let's use code to implement deep cloning:

/** 原型模式(深克隆)
 * 第一步:实现 Cloneable 接口
 * 第二步: 重写一个方法---clone(),同时将该方法进行改造,将克隆对象的属性也进行克隆
 */
public class Video implements Cloneable {
    
     //视频的原型
..................
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        Object obj = super.clone();
        //实现深克隆
        Video v = (Video) obj;
        //将这个对象的属性也进行克隆
        v.createTime = (Date) this.createTime.clone();
        
        return obj;
    }

 .............
}


Insert picture description here
Let's test it with the original client: we can find that changing the date of v1 will not change the date of v2, which means that the object created by deep cloning will not affect the cloned object even if the properties of the prototype object are changed.

There are also serialization and deserialization methods to achieve deep cloning, but because they are all operating IO streams, the efficiency is relatively low. There is no testing here.

Application scenarios of prototype mode

  • Prototype mode rarely appears alone. It usually appears together with the factory method mode. An object is created through the clone method and then provided to the caller by the factory method.
    For example, there are actually two types of bean creation in spring: singleton mode and prototype mode. (Of course, the prototype mode needs to be matched with the factory mode)
  • When creating a large number of objects in a short time, the prototype mode and the common new method efficiency test
  • How to implement inheritance in javascript language? There are prototypes in it.
  • In Spring, @Service is singleton by default. Private global variables are used. If you don't want to affect the next injection or each time the context gets the bean, you need to use the prototype mode. We can achieve it through the following annotation, @Scope("prototype").

Guess you like

Origin blog.csdn.net/weixin_43246215/article/details/108590854