Design Pattern Five: Introduction to prototype mode (PROTOTYPE)
The prototype pattern is one of the creation patterns that creates new objects by copying the prototype objects.
The universal Java Superclass object provides a clone () method to implement a copy of the object.
You can use the prototype pattern in the following scenarios:
- Constructor creation object cost is too high (performance or security cost)
- To save the state of an object with a small change in state, it is not too much memory intensive (more appropriate for state-changed usage mode)
Intention
Use a prototype instance to specify the type of object to create and create a new object by copying the prototype.
Class diagram
Realize
I. The concept of shallow copy and deep copy
Object.clone()
method is to implement a shallow copy of the object, so-called shallow copy is when the object has a complex reference type of the domain variable, only copy the domain variable reference instead of the content, when any one of the laws to modify the state of the domain variable will affect both the prototype object and copy objects, in fact, they share the same heap memory. A deep copy creates an object that is a full copy of the original object and does not affect the state of any other object.
The Cloneable interface is provided in Java, and classes that implement interfaces Cloneable
and override Object.clone()
methods can be used to copy themselves. Cloneable
is a markup interface in which no methods are defined.
Two. The following code demonstrates a deep copy implemented using the Clone () method, which is more suitable for simpler objects, or the implementation of the Clone () method can become unusually complex.
import Lombok. Allargsconstructor;import Lombok. Data; @Data @allargsconstructorpublic class Carproperty implements cloneable {private String power; Private double maxspeed; Private double oilperkm; Public Object Clone () {object obj = null; try {obj = Super.clone (); } catch (Clonenotsupportedexception e) {e.printstacktrace (); } return obj; }}
Import Lombok. Allargsconstructor;import Lombok. Data; @Data @allargsconstructorpublic class Car implements cloneable {private String brand; private double price; Private Carproperty Carproperty; /** * Deep copy in this implementation, for complex application types, the code here can be quite complex, if the class has been modified (new member variable, etc.), here also need to modify * @return */public Object clone () { Object car = null; try {car = Super.clone (); Carproperty Carpropertyclone = (carproperty) this.getcarproperty (). Clone (); ((car) car). Setcarproperty (Carpropertyclone); } catch (Clonenotsupportedexception e) {e.printstacktrace (); } return car; } public static void Main (string[] args) {Carproperty carproperty = new Carproperty ("8 Horses", 250,30); Car car= new Car ("BMW", 200,carproperty); Car copy = (car) car.clone (); System.out.println ("Copy max speed is:" +copy.getcarproperty (). Getmaxspeed ()); SYSTEM.OUT.PRINTLN ("Prototype maximum speed is:" +car.getcarproperty (). Getmaxspeed ()); CaR.getcarproperty (). Setmaxspeed (360); System.out.println ("Copy max speed is:" +copy.getcarproperty (). Getmaxspeed ()); SYSTEM.OUT.PRINTLN ("Prototype maximum speed is:" +car.getcarproperty (). Getmaxspeed ()); }}
Three. Other implementations of deep copies: In addition to the methods above, you can use the reflection mechanism to create deep copies of objects, and another simpler way is to use serialization;
The following code implements a deep copy of the object using serialization, which requires the implementation of the Serializable
interface.
Import java.io.*;p Ublic class Deepclonebase implements Serializable {public Object deepclone () {BYTEARRAYOUTPU TStream bytearrayoutputstream = null; ObjectOutputStream objectoutputstream = null; Bytearrayinputstream bytearrayinputstream = null; ObjectInputStream objectinputstream = null; try {bytearrayoutputstream = new Bytearrayoutputstream (); ObjectOutputStream = new ObjectOutputStream (bytearrayoutputstream); Objectoutputstream.writeobject (this); Bytearrayinputstream = new Bytearrayinputstream (Bytearrayoutputstream.tobytearray ()); ObjectInputStream = new ObjectInputStream (bytearrayinputstream); return Objectinputstream.readobject (); } catch (Exception e) {e.printstacktrace (); } finally {try {bytearrayoutputstream.close (); Objectoutputstream.close (); Bytearrayinputstream.close (); ObjEctinputstream.close (); } catch (Exception e) {e.printstacktrace (); }} return null; }}
import Lombok. Allargsconstructor;import Lombok. Data;import java.io.Serializable; @Data @allargsconstructorpublic class MyCar extends Deepclonebase {private String bran D private double price; Private Carproperty Carproperty; public static void Main (string[] args) throws exception{//note carproperty also needs to implement serializable interface, code is no longer listed separately CARPR Operty carproperty = new Carproperty ("8 Horses", 250,30); MyCar car= New MyCar ("BMW", 200,carproperty); MyCar copy = (MyCar) car.deepclone (); if (copy!=null) {System.out.println ("Copy maximum speed is:" +copy.getcarproperty (). Getmaxspeed ()); SYSTEM.OUT.PRINTLN ("Prototype maximum speed is:" +car.getcarproperty (). Getmaxspeed ()); Car.getcarproperty (). Setmaxspeed (360); System.out.println ("Copy max speed is:" +copy.getcarproperty (). Getmaxspeed ()); SYSTEM.OUT.PRINTLN ("Prototype maximum speed is:" +car.getcarproperty (). Getmaxspeed ()); }else{System.out.println ("Object not copied successfully ...."); } }}
Summarize
Pros: 1. If object creation is more complex, it can simplify the creation process and improve the efficiency; 2. The state of the object can be preserved;
Disadvantage: For clone () mode, if the class has to modify the implementation of clone () needs to be modified, does not conform to the open and closed principle; The clone logic of complex objects may be more complex;
Jdk
Java.lang.object#clone ()