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