1. What is a prototype pattern
Before explaining what the prototype mode is, let's see if we often use get and set to assign values in our project. For example, we receive the parameter paramVo object and assign the parameter to another object
public void saveParam(ParamVo vo){ //To prove the meaning of ParamVo, verify the confirmation password if(!vo.getConfirmPassword().equals(vo.getPassword())){ System.out.println("The password and confirmation password are inconsistent"); return; } Param param = new Param(); //Set login param.setName(vo.getName()); //Set password param.setPassword(vo.getPassword()); //More assignment items ... //Save Param in TODO }
I believe the above code is often seen in many projects. Once there are many assignment parameters, do you think this kind of operation is cumbersome? If the prototype is the prototype mode, it can be solved quickly. That is, the prototype mode refers to using an already created instance as the prototype and creating a new object that is the same or similar to the prototype by copying the prototype object.
Prototype mode is generally applicable to the following scenarios:
- Objects are the same or similar, that is, when only several individual attributes are different.
- The cost of creating objects is large, such as long initialization time, too much CPU, or too much network resources. Resources need to be optimized.
- Creating an object requires cumbersome data preparation or access rights, and needs to improve performance or security.
- This kind of object is widely used in the system, and each caller needs to re assign its properties.
The cloning of prototype pattern can be divided into shallow cloning and deep cloning.
2. Shallow cloning
Shallow cloning refers to the creation of a new object. The properties of the new object are exactly the same as those of the original object. For non basic type properties, it still points to the memory address of the object pointed to by the original property.
Let's design a shallow cloning model. The Object class in Java provides the clone() method of shallow cloning. The specific prototype class can realize the shallow cloning of objects as long as it implements the clonable interface, which is the Abstract prototype class
public class ConcretePrototype implements Cloneable { //Basic type properties private int age; //Non basic type attribute private List hobbys; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List getHobbys() { return hobbys; } public void setHobbys(List hobbys) { this.hobbys = hobbys; } ConcretePrototype(){ System.out.println("The specific prototype was created successfully!"); } @Override public Object clone() throws CloneNotSupportedException { System.out.println("The specific prototype is copied successfully!"); return (ConcretePrototype) super.clone(); }
The test code is as follows:
public class ShallowCloneTest { public static void main(String[] args) throws CloneNotSupportedException { ConcretePrototype obj1 = new ConcretePrototype(); obj1.setAge(18); obj1.setHobbys(Arrays.asList("play a ball","wash one 's feet")); ConcretePrototype obj2 = (ConcretePrototype) obj1.clone(); System.out.println("Clone object obj1 Address value of reference type in:" + obj1.getHobbys()); System.out.println("Clone object obj2 Address value of reference type in:" + obj2.getHobbys()); System.out.println("Object address comparison:" + (obj1.getHobbys() == obj2.getHobbys())); } }
3. Deep cloning
Deep cloning refers to the creation of a new object, and other objects referenced in the attribute will also be cloned, no longer pointing to the original object address. Unlike shallow cloning, it no longer points to the same memory address, but uses serialization and deserialization (different memory addresses)
Let's illustrate with a case: create two new classes, course class and video class. Each course has a corresponding video
Video class:
public class Video implements Serializable { private String videoName; }
Courses:
public class Course implements Cloneable, Serializable { public String courseName; public Video video; public String getCourseName() { return courseName; } public void setCourseName(String courseName) { this.courseName = courseName; } public Video getVideo() { return video; } public void setVideo(Video video) { this.video = video; } @Override protected Object clone() throws CloneNotSupportedException{ return this.deepClone(); } public Object deepClone() { try{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); Course copy = (Course)ois.readObject(); return copy; } catch (Exception e){ e.printStackTrace(); return null; } } public Course shallowClone(Course target) { Course course = new Course(); course.video = target.video; course.courseName = target.courseName; return course; } }
Test code:
public class DeepCloneTest { public static void main(String[] args) throws CloneNotSupportedException { Course course = new Course(); course.setCourseName("JAVA"); course.setVideo(new Video()); try{ Course clone = (Course)course.clone(); System.out.println("Whether the memory address of deep clone is the same:"+(course.video == clone.video)); } catch (Exception e){ e.printStackTrace(); } Course q = new Course(); Course n = q.shallowClone(q); System.out.println("Whether the shallow clone memory address is the same:"+(q.video == n.video)); } }
Observe the memory addresses of deep and shallow clones:
4. Conclusion
Through the above explanation and code demonstration, we can summarize the advantages and disadvantages of the prototype mode:
advantage:
- Java's own prototype mode is based on the replication of memory binary stream, which is better in performance than directly new an object.
- You can use deep cloning to save the state of the object, and use prototype mode to copy the object and save its state, which simplifies the process of creating the object for use when needed (for example, restoring to a certain state in History), and can assist in the implementation of undo operation.
Disadvantages:
- You need to configure a clone method for each class
- clone method is located inside the class. When modifying an existing class, you need to modify the code, which violates the opening and closing principle.
- When implementing deep cloning, you need to write more complex code, and when there are multiple nested references between objects, in order to implement deep cloning, the classes corresponding to each layer of objects must support deep cloning, which will be troublesome to implement. Therefore, deep cloning and shallow cloning need to be used properly.
So far, this paper introduces the shallow cloning and deep cloning of the prototype mode, and takes the actual real case as the code demonstration. Through this chapter, we hope to have a clearer understanding of the prototype mode;
Sample code: https://github.com/lhmyy521125/toher-designmode