definition
Prototype instances are used to specify the kind of objects to create, and new objects are created by copying these prototypes.
The prototype pattern is mainly used for object replication. Its core is the prototype class prototype in the class diagram. Prototype class requires the following two conditions:
implement clonable interface. There is a clonable interface in the java language, which has only one function, that is, to notify the virtual machine at runtime that it can safely use the clone method on the class that implements this interface. In the java virtual machine, only the classes that implement this interface can be copied. Otherwise, CloneNotSupportedException will be thrown at runtime.
override the clone method in the Object class. In Java, the parent class of all classes is the Object class. In the Object class, there is a clone method that returns a copy of the Object. However, the scope of the clone method is of protected type, and general classes cannot call it. Therefore, the Prototype class needs to modify the scope of the clone method to public type.
Prototype pattern is a relatively simple pattern, which is also very easy to understand. Implementing an interface and rewriting a method completes the prototype pattern. In practical applications, prototype patterns rarely appear alone. It is often mixed with other patterns, and its prototype class prototype is often replaced by abstract classes.
example
package com.zhangyu.prototype; //Prototype mode public class Prototype implements Cloneable { @Override protected Prototype clone() { Prototype prototype = null; try { prototype = (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return prototype; } } //Implementation class of prototype pattern class ConcretePrototype extends Prototype { public void show(){ System.out.println("Implementation class of prototype pattern"); } } //main class Main{ public static void main(String[] args) { ConcretePrototype concretePrototype = new ConcretePrototype(); for (int i = 0; i < 10; i++) { ConcretePrototype clone = (ConcretePrototype) concretePrototype.clone(); clone.show(); } } }
Advantages and applicable scenarios of prototype mode
Using prototype mode to create an Object is much better than directly creating a new Object. Because the clone method of Object class is a local method, which directly operates binary streams in memory. Especially when copying large objects, the performance difference is very obvious.
Another advantage of using prototype mode is to simplify the creation of objects, making it as simple as copying and pasting when editing documents.
Because of the above advantages, you can consider using the prototype pattern when you need to create similar objects repeatedly. For example, you need to create objects in a loop. If the object creation process is complex or there are many cycles, using the prototype pattern can not only simplify the creation process, but also greatly improve the overall performance of the system.
Considerations for prototype patterns
copying objects using the prototype pattern does not call the constructor of the class. Because the Object is copied by calling the clone method of the Object class, it directly copies data in memory, so it will not call the constructor of the class. Not only does the code in the constructor not execute, but even the access permissions are invalid for the prototype pattern. Remember the singleton mode? In the singleton mode, you can implement a singleton as long as the access permission of the constructor is set to private. However, the clone method directly ignores the permission of the constructor. Therefore, the singleton pattern conflicts with the prototype pattern, and you should pay special attention to it when using it.
deep and shallow copies. The clone method of the Object class only copies the basic data types in the Object. It does not copy arrays, container objects, reference objects, etc. This is a shallow copy. If you want to implement deep copy, you must copy the arrays, container objects, reference objects, etc. in the prototype pattern. In the deep copy and shallow copy problems, there are 8 basic types and their encapsulation types in java, as well as String types. The rest are shallow copies.
Implement "deep copy and shallow copy" using prototype pattern
In the deep copy and shallow copy problems, there are 8 basic types and their encapsulation types in java, as well as String types. The rest are shallow copies.
Shallow copy
package com.zhangyu.prototype; import java.util.ArrayList; //Prototype mode public class Prototype implements Cloneable { Id id; ArrayList list = new ArrayList(); @Override protected Prototype clone() { Prototype prototype = null; try { prototype = (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return prototype; } } class Id { int num; public Id(int num) { this.num = num; } public void setNum(int num) { this.num = num; } } //Implementation class of prototype pattern class ConcretePrototype extends Prototype { public void show() { System.out.println("id=" + id.num + "," + list); } public void show(String msg) { System.out.println(msg + ",id=" + id.num + "," + list); } } //main class Main { public static void main(String[] args) { ConcretePrototype prototype = new ConcretePrototype(); prototype.id = new Id(1); prototype.list.add(1); prototype.show("prototype"); ConcretePrototype clonetype = (ConcretePrototype) prototype.clone(); clonetype.show("clone"); //Modify prototype prototype.id.setNum(2); prototype.list.add(2); System.out.println("After modifying the prototype"); prototype.show("prototype"); clonetype.show("clone"); } }
prototype,id=1,[1] clone,id=1,[1] After modifying the prototype prototype,id=2,[1, 2] clone,id=2,[1, 2]
Deep copy
1. make the Id class also implement the clonable interface, and modify the clone method to public
2. add the clone method in the Prototype
prototype.list = (ArrayList) this.list.clone();
prototype.id = (Id) this.id.clone();
package com.zhangyu.prototype; import java.util.ArrayList; //Prototype mode public class Prototype implements Cloneable { Id id; ArrayList list = new ArrayList(); @Override protected Prototype clone() { Prototype prototype = null; try { prototype = (Prototype) super.clone(); prototype.list = (ArrayList) this.list.clone(); prototype.id = (Id) this.id.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return prototype; } } class Id implements Cloneable { int num; public Id(int num) { this.num = num; } public void setNum(int num) { this.num = num; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } //Implementation class of prototype pattern class ConcretePrototype extends Prototype { public void show() { System.out.println("id=" + id.num + "," + list); } public void show(String msg) { System.out.println(msg + ",id=" + id.num + "," + list); } } //main class Main { public static void main(String[] args) { ConcretePrototype prototype = new ConcretePrototype(); prototype.id = new Id(11); prototype.list.add(11); prototype.show("prototype"); ConcretePrototype clonetype = (ConcretePrototype) prototype.clone(); clonetype.show("clone"); //Modify prototype prototype.id.setNum(10); prototype.list.add(10); System.out.println("After modifying the prototype"); prototype.show("prototype"); clonetype.show("clone"); } }
prototype,id=11,[11] clone,id=11,[11] After modifying the prototype prototype,id=10,[11, 10] clone,id=11,[11]