1. Definition and usage scenario of prototype pattern
Definition: Specify the type of objects created with prototype instances and create new objects by copying these prototypesUse scenarios:
1) Class initialization requires a lot of resources, including data, hardware resources, etc., which can be avoided by prototype copies.
2) Generating an object through new requires very tedious data preparation or access rights, and prototype mode can be used at this time.
3) When an object needs to be accessed by other objects and each caller may need to modify its value, we can consider using prototype mode to copy multiple objects for caller's use, that is, protective copy.
2. Advantages and disadvantages of prototype model
2.1 advantages
Excellent performanceThe prototype pattern is a copy of the binary stream in memory. It performs better than a direct new object. Especially when a large number of objects are generated in a loop, the prototype pattern can better reflect its advantages.
2.2 disadvantages
Escaping Constructor ConstraintsThis is both his advantage and disadvantage. Copy it directly in memory and the constructor will not execute. Need to be considered in practical application
3. Attention to Realization
1) Constructor does not execute by default2) Shallow copy and deep copy
The method clone provided by the Object class is only a copy of the object, and its internal arrays, reference objects, etc. are not copied, or point to the internal element address of the prototype object, which is a shallow copy. If a deep copy is required, the corresponding member should also point to the clone method.
3) To use the clone method, do not add final keywords to the member variables of the class
4. Implementation of prototype pattern
ProtoType: public class ProtoType implements Cloneable { public ProtoType() { System.out.println("ProtoType is excute..."); } private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected ProtoType clone() { ProtoType protoType = null; try { protoType = (ProtoType) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return protoType; } @Override public String toString() { return "ProtoType{" + "id=" + id + ", name='" + name + '\'' + '}'; } } Text: public class Test { public static void main(String args[]) { ProtoType type = new ProtoType(); type.setId(1); type.setName("Zhang San"); System.out.println(type); ProtoType clone = type.clone(); clone.setId(2); clone.setName("Li Si"); System.out.println(clone); } }
You can see that a native method is executed to execute a copy of the binary streamObjec Of clone Source code: /** * Creates and returns a copy of this {@code Object}. The default * implementation returns a so-called "shallow" copy: It creates a new * instance of the same class and then copies the field values (including * object references) from this instance to the new instance. A "deep" copy, * in contrast, would also recursively clone nested objects. A subclass that * needs to implement this kind of cloning should call {@code super.clone()} * to create the new instance and then create deep copies of the nested, * mutable objects. * * @return a copy of this object. * @throws CloneNotSupportedException * if this object's class does not implement the {@code * Cloneable} interface. */ protected Object clone() throws CloneNotSupportedException { if (!(this instanceof Cloneable)) { throw new CloneNotSupportedException("Class " + getClass().getName() + " doesn't implement Cloneable"); } return internalClone(); } /* * Native helper method for cloning. */ private native Object internalClone();
5. Application of prototype pattern in Android
Intent: @Override public Object clone() { return new Intent(this); } /** * 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 = new ArraySet<String>(o.mCategories); } if (o.mExtras != null) { this.mExtras = new Bundle(o.mExtras); } if (o.mSourceBounds != null) { this.mSourceBounds = new Rect(o.mSourceBounds); } if (o.mSelector != null) { this.mSelector = new Intent(o.mSelector); } if (o.mClipData != null) { this.mClipData = new ClipData(o.mClipData); } }