Prototype mode is also a creation of a design pattern, from the name can be understood, this pattern should have a template instance, that is, the prototype, and then the user from the prototype copy of an internal attribute consistent instance, that is, cloning.
Sometimes, when an object is constructed more complex and time-consuming, it is more efficient to copy an instance directly from an existing object than to reconstruct it.
Jane's book Address
Defined
Use the prototype instance to specify the kind of object to create and create a new object by copying the prototypes.
Usage Scenarios
- Initialization of objects consumes a lot of resources, including hardware, data, and so on. You can use prototype mode to avoid the consumption of this resource.
- You can use prototype mode when you instantiate an object with new to require very tedious data preparation or access permissions.
- When an object is to be accessed by other objects, and each caller is likely to modify his value, consider copying multiple prototypes of objects in prototype mode for use by each caller, without affecting each other, that is, a protective copy.
- When you need to create similar objects frequently, such as creating objects in a loop.
This shows that using clone to produce an instance is not necessarily faster than new, and when some objects are constructed very simply, new is faster than clone. However, when the construction of the object is complicated, the new structure will cause a large cost, then clone can show the advantage of efficiency.
UML Class Diagram
Where prototype does not have to implement the Cloneable interface, there are two types of presentations.
Simple implementation using the Cloneable interface
Prototype to implement the Cloneable interface:
publicclass Prototype implements Cloneable{ }
The implementation of the prototype:
Public class concreteprototype extends Prototype { PublicString name; Publicarraylist<string> list =NewArraylist<> (); Public Concreteprototype() {System.out.println ("Concreteprototype Constructor was executed"); }@Override PublicConcreteprototypeClone() {Concreteprototype prototype =NULL;Try{prototype = (Concreteprototype)Super. Clone (); }Catch(Clonenotsupportedexception e) {E.printstacktrace (); }returnPrototype }@Override PublicStringtoString() {return "concreteprototype{"+"Name= '"+ name +' \ '+", list="+ list +'} '; }}
Use:
public class Mainm {public static void main (string[] args) {Concreteprototype Concreteprototype = new Concrete Prototype ();Concreteprototype. Name="Yuanxing";Concreteprototype. List. Add("Yuanxing1");Concreteprototype. List. Add("Yuanxing2");Concreteprototype. List. Add("Yuanxing3");Concreteprototype Cloneconcreteprototype = (concreteprototype) concreteprototype. Clone();Cloneconcreteprototype. Name="Clone";System. out. println(Concreteprototype. toString());System. out. println(Cloneconcreteprototype. toString());}}
Output:
An instance is obtained by using the Clone method, and modifying the contents of the instance does not affect the contents of the original instance.
This, of course, is only valid for basic data types.
Do not implement Cloneable interface
Prototype:
publicclass Prototype1 {}
The implementation of the prototype:
Public class ConcretePrototype1 extends Prototype1 { PublicString name; Publicarraylist<string> list =NewArraylist<> (); Public ConcretePrototype1() {System.out.println ("Concreteprototype Constructor was executed"); } PublicConcretePrototype1Clone() {ConcretePrototype1 prototype1 =NewConcretePrototype1 (); Prototype1.name = This. Name; prototype1.list= This. List;returnPrototype1; }@Override PublicStringtoString() {return "concreteprototype1{"+"Name= '"+ name +' \ '+", list="+ list +'} '; }}
Use:
public class Mainm {public static void main (string[] args) {ConcretePrototype1 concretePrototype1 = new Concre TePrototype1 ();ConcretePrototype1. Name="Yuanxing";ConcretePrototype1. List. Add("Yuanxing1");ConcretePrototype1. List. Add("Yuanxing2");ConcretePrototype1. List. Add("Yuanxing3");ConcretePrototype1 cloneconcretePrototype1 = (ConcretePrototype1) concretePrototype1. Clone();CloneconcretePrototype1. Name="Clone";System. out. println(ConcretePrototype1. toString());System. out. println(CloneconcretePrototype1. toString());}}
The result of the output is a bit different:
The method of calling Cloneable directly does not call the construction method again, and your new is bound to call the constructor method.
I personally think this should be a pseudo-clone, just write a clone method, and then in the method to new an object, and then to manually assign their own value to the new object.
Problem
All two of the above tests the Name property, what if the ArrayList object list is modified in the cloned object? To try:
Use:
public class Mainm {public static void main (string[] args) {Concreteprototype Concreteprototype = new Concrete Prototype ();Concreteprototype. Name="Yuanxing";Concreteprototype. List. Add("Yuanxing1");Concreteprototype. List. Add("Yuanxing2");Concreteprototype. List. Add("Yuanxing3");Concreteprototype Cloneconcreteprototype = (concreteprototype) concreteprototype. Clone();Cloneconcreteprototype. Name="Clone";Cloneconcreteprototype. List. Add("Clone1");System. out. println(Concreteprototype. toString());System. out. println(Cloneconcreteprototype. toString());}}
The discovery output is not expected:
A list of cloned objects has been modified, and the value of list in the prototype has changed.
Deep copy-Shallow copy
This occurs because a shallow copy is used in the previous prototype. Cloneable method Clone is a shallow copy by default, and a shallow copy does not reconstruct all the fields, but refers to the fields in the prototype. For value types, which are basic data types, there is also a string type, and the Clone method makes a copy that allows the copied objects and prototypes to interfere with each other. However, for reference types (objects, collections, arrays, and so on), the Clone method simply points them to the same memory address, so modifying one of them will change the contents of each of the two.
So for a property that is not of the base type, you manually invoke the Clone method of the Reference object at clone, which is a deep copy.
Add a deep copy of the overridden Clone method
@Override publicclone() { null; try { super.clone(); this.list.clone(); catch (CloneNotSupportedException e) { e.printStackTrace(); } return prototype; }
Then we will get the output we expect:
Prototype mode in Android Source:
The prototype pattern may rarely be used alone, in the case of the book is a intent, although the Cloneable interface is implemented, but in the Clone method is a direct new intent, the prototype is passed in, and then copied to the new intent:
PackageAndroid.content; Public class Intent implements parcelable, cloneable { /** * Copy constructor * / Public Intent(Intent o) { This. maction = o.maction; This. Mdata = O.mdata; This. mtype = O.mtype; This. mpackage = O.mpackage; This. mcomponent = o.mcomponent; This. mflags = O.mflags; This. Mcontentuserhint = O.mcontentuserhint;if(O.mcategories! =NULL) { This. mcategories =NewArrayset<string> (o.mcategories); }if(O.mextras! =NULL) { This. Mextras =NewBundle (O.mextras); }if(O.msourcebounds! =NULL) { This. Msourcebounds =NewRect (O.msourcebounds); }if(O.mselector! =NULL) { This. Mselector =NewIntent (O.mselector); }if(O.mclipdata! =NULL) { This. Mclipdata =NewClipdata (O.mclipdata); } }@Override PublicObjectClone() {return NewIntent ( This); } }
What you might consider here is that direct new is faster than clone.
Summarize
Prototype mode is mainly copying objects, copying objects generally have two functions
1. The protection prototype is not modified, providing only one copy for external access, and a protective copy.
2. Avoid the problem of resource consumption when constructing complex objects, and improve the efficiency of creating objects.
Advantages
- The Clone method of object is a local method that directly operates on a binary stream and performs much better.
Disadvantages
- The construction method will not be executed at clone, which is both an advantage and a disadvantage, and should be paid attention to when using this potential problem.
Android design mode (iii)-prototype mode