Contents of article series (continuously updated) :

Chapter 1: Overview, Coupling, UML, Seven Principles, Detailed Analysis and summary (Based on Java)

Chapter two: Several implementations of singleton pattern And its destruction by reflection

【 Design Pattern 】 Chapter 3: A Simple factory, factory method pattern, abstract factory pattern 】

The Builder model is not that difficult

Chapter 5: What is a Prototype Pattern? Shallow fetch shallow copy and deep copy

Article 6: Look at the adapter pattern

[Design Pattern] Chapter 7: Understand the bridge pattern with me

[Design mode] Chapter 8: Drinking soy milk is decorator mode?

[Design Pattern] Chapter 9: Combination pattern to solve the problem of hierarchical structure

[Design mode] Chapter 10: Appearance mode, the joy of driving a small broken car

[Design mode] Chapter 11: Let’s take a look at the yuan model

[Design Mode] Chapter 12: explanation of agent mode in the ticket purchase scene

A prototype pattern is introduced

The prototype pattern, as the last of the creation patterns, does not involve much, so let’s take a look

Let’s take a life example, for example, we want to publish a book, and there are some information fields, such as title price and so on

public class Book {
    private String name; / / name
    private int price; / / price
    private Partner partner; // Partners
    // omit constructor, get set, toString, etc
}
Copy the code

The reference type Partner is also simple

public class Partner{
    private String name;
    
// omit constructor, get set, toString, etc
}
Copy the code

(a) Direct new

You can’t just publish a book. How do you mass-produce it?

Some people might think that, like the following, each new (or even write a for loop), let’s not mention the efficiency of a lot of new, first of all, I have to re-copy the new object, like, every time I print a book, I have to re-write it.

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
		// Initialize a partner type
        Partner partner = new Partner("Zhang");
		// Parameter assignment
        Book bookA = new Book("More than twenty years of ideal.".66, partner);
        Book bookB = new Book("More than twenty years of ideal.".66, partner);

        System.out.println("A: " + bookA.toString());
        System.out.println("A: " + bookA.hashCode());
	    System.out.println("B: " + bookB.toString());
      	System.out.println("B: "+ bookB.hashCode()); }}Copy the code

Some students may also have thought of creating A first, and then assign the value to B and C….. Wait, but this is actually passing references rather than values, which is like writing on C and B, see A for details

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {

        // Initialize a partner type
        Partner partner = new Partner("Zhang");
        // Parameter assignment
        Book bookA = new Book("More than twenty years of ideal.".66, partner);

        System.out.println("A: " + bookA.toString());
        System.out.println("A: " + bookA.hashCode());
        
        // Reference assignment
        Book bookB = bookA;
        
        System.out.println("B: " + bookB.toString());
        System.out.println("B: "+ bookB.hashCode()); }}Copy the code

These two are obviously not, our normal idea is that the author only needs to write a book content, first print a, if it can, according to this sample for large quantities of the same color copy, and the above method of quoting is obviously not appropriate, which requires the use of Java cloning

(2) shallow clone

To use cloning, the Book class is processed first

  • First implement the Cloneable interface
  • Next, override the Clone method
public class Book implements Cloneable{
    private String name; / / name
    private int price; / / price
    private Partner partner; // Partners

    @Override
    protected Object clone(a) throws CloneNotSupportedException {
        return super.clone();
    }
    
    // omit constructor, get set, toString, etc
}

Copy the code

Let’s test it out again

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        // Initialize a partner type
        Partner partner = new Partner("Zhang");
        // Parameter assignment
        Book bookA = new Book("More than twenty years of ideal.".66, partner);
        // B clone A
        Book bookB = (Book) bookA.clone();

        System.out.println("A: " + bookA.toString());
        System.out.println("A: " + bookA.hashCode());
        System.out.println("B: " + bookB.toString());
        System.out.println("B: "+ bookB.hashCode()); }}Copy the code

The execution result

A: Book{name=’ ideal ‘, price=66, partner= partner {name= zhang3}} A: 460141958 B: Price =66, partner= partner {name= zhang3}} B: 1163157884

The result is very clear, the book information is the same, but the memory address is not the same, that is, the clone is successful, print its hashCode and find that the two are not identical, indicating that not only pointing to the same, but also meet our requirements

That’s not the end of it, you’ll find that there are still problems, when you change the content of some values in the process of printing, you see the effect

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        // Initialize a partner type
        Partner partner = new Partner("Zhang");
        // Parameter assignment
        Book bookA = new Book("More than twenty years of ideal.".66, partner);
        // B clone A
        Book bookB = (Book) bookA.clone();
        // Modify the data
        partner.setName("Bill");

        System.out.println("A: " + bookA.toString());
        System.out.println("A: " + bookA.hashCode());
        System.out.println("B: " + bookB.toString());
        System.out.println("B: "+ bookB.hashCode()); }}Copy the code

The execution result

A: Book{name=’ ideal ‘, price=66, partner= partner {name= lI si}} A: 460141958 B: Book{name}, price=66, partner= partner {name}} B: 1163157884

????? B cloned A first. Why did I modify the value of one of A after cloning, but B also changed

This is a typical shallow clone. In the Book class, when the field is a reference type, such as the Partner class, which is our own custom class, the copy reference does not assign the reference object. Therefore, the original object and the copied Partner object refer to the same object

(3) deep cloning

To solve the above problem, we need to rewrite the contents of clone and implement shallow clone in the reference type

(1) The referenced type realizes shallow clone

The full code is as follows

public class Partner implements Cloneable {
    private String name;

    @Override
    protected Object clone(a) throws CloneNotSupportedException {
        return super.clone();
    }
    // omit constructor, get set, toString, etc
}
Copy the code

(2) Modify the cloen method of reference class

public class Book implements Cloneable{
    private String name; / / name
    private int price; / / price
    private Partner partner; // Partners

    @Override
    protected Object clone(a) throws CloneNotSupportedException {
		Object clone = super.clone();
        Book book = (Book) clone;
        book.partner =(Partner) this.partner.clone();
        return clone;
    }
	// omit constructor, get set, toString, etc
}
Copy the code

Test the

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        // Initialize a partner type
        Partner partner = new Partner("Zhang");
        // Parameter assignment
        Book bookA = new Book("More than twenty years of ideal.".66, partner);
        // B clone A
        Book bookB = (Book) bookA.clone();
        // Modify the data
        partner.setName("Bill");

        System.out.println("A: " + bookA.toString());
        System.out.println("A: " + bookA.hashCode());
        System.out.println("B: " + bookB.toString());
        System.out.println("B: "+ bookB.hashCode()); }}Copy the code

perform

A: Book{name=’ ideal ‘, price=66, partner= partner {name= lI si}} A: 460141958 B: Price =66, partner= partner {name= zhang3}} B: 1163157884

As you can see, after B clones A, it changes the value of A’s partner without being affected, which is exactly what we wanted to achieve in the beginning

Two prototype pattern theory

(A) What is the prototype pattern

In some programs, it may be necessary to create a large number of identical or similar objects. Creating objects through traditional constructors many times, when the constructor execution is slow, can be complicated and expensive, and the details of the creation are exposed

The prototype pattern can help us solve this problem

Definition: A prototype pattern, in which prototype instances specify the type of objects to be created and new objects to be created by copying these prototypes

(2) Structure

According to the structure diagram, a brief description of the roles:

  • Abstract Prototype classes: Specify the interfaces that concrete Prototype objects must implement
  • ConcretePrototype: implements the clone method, which is an operation that clones itself
  • Access class (Client) : Create a new object by cloning itself using the Clone method in the concrete prototype class

(iii) Two modes

It can also be seen from the above example that the prototype mode is divided into shallow clone and deep clone

  • Shallow clone: Create a new object with the same attributes as the original object. For non-basic attributes, the new object still points to the memory address of the object pointed to by the original attribute
  • Clone: When a new object is created, other objects referenced in the property will also be cloned, instead of pointing to the original object address.

(4) Advantages and disadvantages

Advantages:

  • The Java archetypal pattern is based on in-memory binary stream replication, which provides better performance than direct New

  • Deep cloning can be used to preserve object state, save a copy of the old (cloned), when modified, can act as an undo function

Disadvantages:

  • Clone method needs to be configured. Existing classes need to be modified during transformation, which violates the “open and close principle”.
  • If there are multiple nested references between objects, each layer needs to be cloned
    • For example, in the above example, deep clone is realized in Book, and shallow clone is realized in Partner, so we should pay attention to the proper use of deep and shallow clone