This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.


Hello, everyone, I am a ~

Before the “vernacular design mode” because of the work was shelved, now set sail again, and with the framework source code analysis together to eat, the theory and practice perfect combination.

Students who are not familiar with design patterns can first read “23 Kinds of Design patterns in one Sentence popular Interpretation” to have a comprehensive understanding of design patterns, form an overall framework, and then break down one by one.

Today we’ll take a look at the prototype pattern, which is a simple and common one.

define

The official definition of

Specify the type of object to create with a prototype instance, and create new objects by copying the prototype.

Easy to interpret

When duplicate objects need to be created, ontology provides a clone for external use in order to ensure performance.

Similar to printing in China, the process of new is omitted and objects are created by copy.

chart

Code implementation

The directory structure

It is recommended that anyone learning design patterns build a Maven project and install Lombok dependencies and plug-ins.

And set up the following package directory for easy induction and arrangement.

Pom as follows

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.10</version>
    </dependency>

Copy the code

Development scenarios

Suppose that a framework named YitiaoBatis is developed to replace Mybatis. Every time we operate the database, we can find out a lot of records from the database, but there are few changes. If we check the database every time and package all the data into one object, many duplicate objects will be new, resulting in a waste of resources.

One of the solutions he came up with was to save the data he had checked, and then search for the same data and return the saved object directly, which was the idea of caching.

Let’s simulate this in code:

1. CreateYitiaoEntity class

/** * author: */
@Data
@AllArgsConstructor
public class Yitiao {
    
    private String name;
    private Integer id;
    private String wechat;

    public Yitiao(a){
        System.out.println("Yitiao object creation"); }}Copy the code

2. To createYitiaoBatisclass

/** * author: */
public class YitiaoBatis {
    / / cache the Map
    private Map<String,Yitiao> yitiaoCache = new HashMap<>();

    // Fetch objects from the cache
    public Yitiao getYitiao(String name){
        // Check whether the cache exists
        if (yitiaoCache.containsKey(name)){
            Yitiao yitiao = yitiaoCache.get(name);
            System.out.println("Check data from cache:"+yitiao);
            return yitiao;
        }else {
            // query data from a database
            Yitiao yitiao = new Yitiao();
            yitiao.setName(name);
            yitiao.setId(1);
            yitiao.setWechat("Public number: a coding");
            System.out.println("Check data from database :"+yitiao);
            // Put it in the cache
            yitiaoCache.put(name,yitiao);
            returnyitiao; }}}Copy the code

3. Write test classes

/** * author: */
public class MainTest {
    public static void main(String[] args) {
        YitiaoBatis yitiaoBatis = new YitiaoBatis();
        Yitiao yitiao1 = yitiaoBatis.getYitiao("yitiao");
        System.out.println("First query:"+yitiao1);
        Yitiao yitiao2 = yitiaoBatis.getYitiao("yitiao");
        System.out.println("Second query:"+yitiao2); }}Copy the code

The output

As can be seen from the results:

  • Object is created once, sort of singleton style
  • First check from the database, second check from the cache

It seems that YitiaoBatis framework needs to be implemented, think about 🤔 what is the problem?

4. Change the object ID

Continue writing in the test class

// Perform subsequent services and change the ID
yitiao2.setId(100);

Yitiao yitiao3 = yitiaoBatis.getYitiao("yitiao");
System.out.println("Third query:"+yitiao3);
Copy the code

The output

Id =100?

When we modify data in memory, the data detected from the database also changes, resulting in dirty data.

How do you solve it? Prototype mode is officially underway.

5. ImplementCloneableinterface

The ontology provides a clone for external use. Objects retrieved from the cache are not returned directly, but copied, thus ensuring that the cache is not dirty.

public class Yitiao implements Cloneable{
  
  	/ /...
  
		@Override
    protected Object clone(a) throws CloneNotSupportedException {
				return (Yitiao) super.clone(); }}Copy the code

Modify the cache


// Fetch objects from the cache
    public Yitiao getYitiao(String name) throws CloneNotSupportedException {
        // Check whether the cache exists
        if (yitiaoCache.containsKey(name)){
            Yitiao yitiao = yitiaoCache.get(name);
            System.out.println("Check data from cache:"+yitiao);
            // Modify return
            //return yitiao;
            return yitiao.clone();
        }else {
            // query data from a database
            Yitiao yitiao = new Yitiao();
            yitiao.setName(name);
            yitiao.setId(1);
            yitiao.setWechat("Public number: a coding");
            System.out.println("Check data from database :"+yitiao);
            // Put it in the cache
            yitiaoCache.put(name,yitiao);
            // Modify return
            //return yitiao;
            return yitiao.clone();
        }
Copy the code

6. Test again

Instead of changing the test class, take a look at the results:

From the output, you can see that the id of the third query is still 1, and there is no dirty cache.

Based on the idea of cloning in prototype mode, I can quickly get the “clone” which is exactly the same as the “ontology”, and the object is only new once.

If you’re wondering how objects are created, let’s take a look at “deep copy” and “shallow copy”.

Deep copy and shallow copy

define

Deep copy: Copies a full copy of a new object, regardless of whether the original or reference data type is in the copied object.

Shallow copy: When the copied object contains only simple data types such as int, float, or immutable objects (strings), these fields are copied directly into the new object. Instead of copying the referenced object, the address of the referenced object is copied to the cloned object.

Like two brothers, deep copy is young when the relationship is particularly good, buy the same clothes, house to live together. Shallow copy is grown up to have a family, clothes can continue to buy the same, but the house must be separated.

implementation

The way to distinguish deep copy from shallow copy in code is to see if the value of a variable of a reference type changes after modification.

Shallow copy

1. Use clone() to create a shallow copy

Create a new Age class as a reference property for Yitiao

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Age {
    private int age;
}
Copy the code

2. Test 1

public static void main(String[] args) throws CloneNotSupportedException {
        Yitiao yitiao1 = new Yitiao();
        Age age = new Age(1);
        yitiao1.setAge(age);
        yitiao1.setId(1);
        Yitiao clone = yitiao1.clone();
        yitiao1.setId(2);
        age.setAge(2);    // Can not new an age
        System.out.println("yitiao1:\n"+yitiao1+"\nclone:\n"+clone);
    }
Copy the code

The output

Conclusion: The base type id does not change. The reference type Age changes because the address points to the same object.

3. Construct a shallow copy

Yitiao.class adds a constructor

    public Yitiao(Yitiao yitiao){
        id=yitiao.id;
        age=yitiao.age;
    }
Copy the code

4. Test 2

        Yitiao yitiao1 = new Yitiao();
        Age age = new Age(1);
        yitiao1.setAge(age);
        yitiao1.setId(1);
        Yitiao clone = new Yitiao(yitiao1);  // This is the difference
        yitiao1.setId(2);
        age.setAge(2);
        System.out.println("yitiao1:\n"+yitiao1+"\nclone:\n"+clone);
Copy the code

The output

Same as test 1

Deep copy

1. Implement deep copy through object serialization

Deep copy is also possible by calling the Clone method horizontally, but the code is too large. In particular, it would be too tedious to override the Clone method for each class with a large number of attributes and a deep hierarchy. Generally not used, and no more examples.

Deep copy can be achieved perfectly by serializing an object to a sequence of bytes, which by default serializes the entire object graph of the object.

Yitiao and Age implement Serializable interfaces

2. The test

// Implement deep copy through object serialization
        Yitiao yitiao = new Yitiao();
        Age age = new Age(1);
        yitiao.setAge(age);
        yitiao.setId(1);
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(yitiao);
        oos.flush();
        ObjectInputStream ois=new ObjectInputStream(new 							ByteArrayInputStream(bos.toByteArray()));
        Yitiao clone = (Yitiao) ois.readObject();
        yitiao.setId(2);
        age.setAge(2);
        System.out.println("yitiao:\n"+yitiao+"\nclone:\n"+clone);
Copy the code

The output

In conclusion, the reference object is also completely copied to a new one, with no change in value.

Note, however, that if a property is transient, it cannot be copied.

Application scenarios

Let’s go back to the prototype pattern.

The prototype pattern is a common but often overlooked pattern in our code, such as beanutils.copyProperties, which is a shallow copy of an object.

Take a look at what scenarios require a prototype pattern

  • Resource optimization
  • Performance and safety requirements
  • A scenario where an object has multiple modifiers.
  • When an object needs to be made available to other objects, and each caller may need to modify its value, consider using the prototype pattern to copy multiple objects for use by the caller.

The prototype pattern has been integrated into Java and can be used at will.

conclusion

Prototype mode is probably the simplest design mode besides singletons, but I still wrote for nearly 4 hours, drawing, typing, coding, and writing 8000 words without realizing it.

A high-quality original article is really a cost of the author’s efforts, so if the feeling of writing is good, trouble to three even, this is very important for a, but also a creative power!

The last

As the old saying goes: revolution by the wisdom of the masses, is no matter what; With the strength of many, there is no victory. ** A person may go fast, but a group of people can go farther.

To this end, I made a group growth plan and shared 1-3 high-quality articles and 1 Leetcode algorithm problem every day

If you’re a freshman and you study every day, you’ll have read at least 4,000 more articles and checked 1,200 more questions, and you’ll be earning 3-4 times as much when you graduate.

If you are a professional, you can improve yourself every day, get a promotion and raise, and become a technical expert.

As long as you are willing to struggle, always walk on the road of hard work, that your life, the worst result, but is a late bloomer.

Click here to join the program

If the link is blocked, or there is a permission problem, you can private chat author to solve.

Fan-only benefits

📚 Java interview:

📚 Java advanced:

📚 Java books:

📚 Java books:

Focus on
Extract the code