This article has participated in the call for good writing activities, click to view: [Back end, big front-end double track submission, 20,000 yuan prize pool waiting for you to challenge!]

Introduction to the

The prototype pattern is a creative design pattern. The prototype indicates that the pattern has a sample instance, from which the user copies an object with consistent internal properties, which is commonly referred to as a clone. The copied object is the prototype. The prototype pattern is often used to create complex or time-consuming instances, and copying an existing instance can make the program run more efficiently.

Class relationships

  • Client: indicates the Client user
  • Prototype: Abstract class or interface with Clone capability
  • ConcretePrototype: ConcretePrototype class

A prototype pattern is a very simple pattern that implements an interface, overrides a method and completes the prototype pattern. When an object creation process is complex, such as creating multiple fields, we can copy the existing object without worrying about the details of the creation.

Simple implementation

Cloneable interface and its implementation classes

First, the prototype class needs to implement the java.lang.cloneable interface and then override the Clone () method in Object. Cloneable is a tag interface that only classes that implement Cloneable can clone objects. If this interface is not implemented, an exception is thrown

Now let’s write a prototype class and implement the Cloneable interface

Public class Document implements Cloneable{private String mText; private String mText2; private String mText3; private String mText4; // a variable of reference type private UserInfo UserInfo; Public Document(String mText, String mText2, String mText3, String mText4, UserInfo UserInfo) {super(); this.mText = mText; this.mText2 = mText2; this.mText3 = mText3; this.mText4 = mText4; this.userInfo = userInfo; } / / clone method returns. Super clone () returns the Object @ Override protected Object clone () throws CloneNotSupportedException {the Document document = (Document)super.clone(); return document; } @Override public String toString() { return "Document [hashCode="+this.hashCode()+", "+"mText=" + mText + ", mText2=" + mText2 + ", mText3=" + mText3 + ", mText4=" + mText4 + ", userInfo=" + userInfo +"]"; }...Copy the code

Reference class UserInfo (used to demonstrate reference type variables)

public class UserInfo implements Cloneable{ public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "UserInfo [name=" + name + "]"; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}Copy the code

As can be seen from the Document class, since its constructor requires many parameters, the cost of constructing an object is very high. Therefore, in this case, clone can be considered to create the object, which can save a lot of cost.

The Client implementation

public class Client { public static void main(String[] args) throws CloneNotSupportedException { UserInfo userInfo = new  UserInfo(); userInfo.setName("xxx"); Document Document = new Document("1","2","3","4",userInfo); Document Clone = (document)document.clone(); System.out.println("document="+document); System.out.println("clone="+clone); }}Copy the code

The document.clone() method is a simple way to get a cloned object and view the printed result

document=Document [hashCode=2018699554, mText=1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=xxx]]
clone=Document [hashCode=1311053135, mText=1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=xxx]]
Copy the code

You can see that the hashCode value of the Clone object is different from that of the original object, meaning that these are two different objects. This way you can easily create objects.

Deep copy and shallow copy

Shallow copy

If an object has a reference type, such as UserInfo, it may cause some problems when we try to modify the reference. Now modify the value of the cloned object and print it

public static void main(String[] args) throws CloneNotSupportedException { UserInfo userInfo = new UserInfo(); userInfo.setName("xxx"); Document document = new Document("1","2","3","4",userInfo); // Modify the String type of the original object document.setmtext ("text1"); Document Clone = (Document)document.clone(); UserInfo clone.getUserInfo().setName("yyy"); // Change the reference data type of the clone object. // Modify the clone object's String variable clone.setmText("text2"); System.out.println("document="+document); System.out.println("clone="+clone); }Copy the code

I obtained the clone object through clone method, and modified the content of the userinfo of the clone object, and modified the String type of the original object and the clone object. Let’s see the result

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=yyy]]
clone=Document [hashCode=1311053135, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=yyy]]
Copy the code

Sees a problem, I just changed the clone the userinfo object, but the original object the userinfo also changed, from here we can see that to a reference type variable, the cloned object and the original object point to the same piece of memory space, when the object changes, the original object and the cloned object will have corresponding change, Let’s modify the printing of UserInfo to include its memory address

 UserInfo.java
 
	@Override
	public String toString() {
		return "UserInfo [hashcode="+this.hashCode()+", "+"name=" + name + "]";
	}
Copy the code

Print Client again

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=yyy]]
clone=Document [hashCode=118352462, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=yyy]]
Copy the code

As you can see, the document userInfo and the Clone object’s userInfo point to the same address.

Deep copy

How should such a problem be solved? Let’s modify the Clone method of Document

Document.java @Override protected Object clone() throws CloneNotSupportedException { Document document = (Document)super.clone(); // Clone document.setUserinfo ((UserInfo) userinfo.clone ()); return document; }Copy the code

Through the above modification, let’s perform the printing operation again

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=xxx]]
clone=Document [hashCode=118352462, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1550089733, name=yyy]]
Copy the code

See, the print is different this time, only the value of the cloned object is changed, but the value of the original object is not changed, and the address of the userinfo they point to is also different, this is the deep copy.

summary

We saw the prototype pattern through an example, and understood the meaning of deep copy and shallow copy by modifying a reference type variable. Here we summarize the concepts of both.

Shallow copy: is the prototype object of a member variable is a property of a value type is assigned to the cloned object, the member variables in the prototype object of a reference type reference address also copy to clone objects, if a member variable of the prototype object as the object of drinking, this address is Shared with the prototype object reference object and cloned objects. Shallow copy copies only the prototype object, but not the object it refers to.

Deep copy: Copies all types of the prototype object, whether value types or reference types, to the clone. Deep copy copies both the prototype object and the objects referenced by the prototype object to the clone.