What
Prototype: Use a prototype instance to specify the type of the object to be created, and copy the prototype to create a new object.
Why
Prototype is applicable when a class instance has several different combinations of States, it is easier to create a prototype and clone them, than to create them with the appropriate status each time, or, to avoid creating a factory class level that is parallel to the product class level, the class to be instantiated is dynamically specified at runtime.
How
Assume that there is a complicated report, and the creation process is very complex. You need to send the report to two leaders. Only reports with different attributes are missing, and other attributes are the same.
First, we will discuss the basic knowledge in Java.
Java clone () method:
The clone method copies an object and returns it to the caller. Generally, the following conditions are met:
1. For any object A, there is a. Clone ()! = X. The cloned object and source object are different objects.
2. For any object A, there is a. Clone (). getclass () = A. getclass (). The cloned object is of the same type as the source object.
3. If the equals () method of object A is properly defined, A. Clone (). Equals (a) is true.
Implementation of object cloning in Java:
You can use the clone () method of the object class.
1. Implement the coneable interface of the object class
2. overwrite the clone () method
3. Call super. Clone () to clone the instance.
The above implementation code is as follows:
public class Product implements Cloneable{ private String name; private int model; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getModel() { return model; } public void setModel(int model) { this.model = model; } @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }}
public class Report implements Cloneable{ private String name; private Product product; public String getName() { return name; } public void setName(String name) { this.name = name; } public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }}
Client call
Public classApp{Public static void main (string [] ARGs) {Report report = new report (); product Product = new product (); product. setmodel (1); product. setname ("productname"); report. setname ("XX Product Report"); report. setproduct (product); system. out. println (report. getname () + "|" + report. getproduct (). getname (); report report1 = (report) report. clone (); report1.setname ("XX Product Report Group 1"); report1.getproduct (). setname ("Product 1"); system. out. println (report1.getname () + "|" + report1.getproduct (). getname ());}}
The above code class diagram is as follows:
Discuss
Deep copy vs light copy
In the preceding example, the running result is as follows:
Product Report | productname Product Report Group 1 | product 1
We are adding a line of code to print the report information in the last line.
System.out.println(report.getName()+"|"+report.getProduct().getName());
The running result is as follows:
Product Report | productname Product Report Group 1 | product 1 product report | product 1
We can see that the product name in the report has been changed because of a problem in the result of the second printing.
In the report, the product attribute references other objects. In the clone method, our implementation only copies its reference and only takes charge of its pointer, the property in the heap space to which it points is not copied, so in this line of code report1.getproduct (). setname ("Product 1"); also changes the value of the name attribute in the product attribute in the report. This copy is a shortest copy.
Modify the clone () method of the report as follows:
@Override protected Object clone() { Report report; try { report=(Report) super.clone(); report.setProduct((Product)product.clone()); return report; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; }
Let's take a look at the running results.
XX product report | productname XX Product Report Group 1 | product 1 XX product report | productname
The result is correct. In the above Code, we also clone the product attribute, so the product attributes of report1 and report point to different heap spaces, therefore, changing the property values in the product does not affect each other. This copy is a deep copy.