Learning goals
- Knowledge of prototype patterns and builder application scenarios
- Master the writing method of shallow clone and deep clone of prototype mode
- Master the basic writing of builder mode
- Understand how cloning breaks singletons
- Understand the pros and cons of prototyping patterns
- Learn the difference between builder mode and factory mode
Definition of archetypal patterns
- A Prototype Pattern is an instance of a Prototype that specifies the type of object to create and that is innovated by copying those prototypes.
- The caller does not need to know any creation details and does not call the constructor
- Belongs to the creation mode
The application scenario of the prototype pattern
- Class initialization consumes many resources
- An object produced by new requires a very tedious process (data preparation, access rights, etc.)
- Constructors are more complex
- When a large number of objects are produced in a loop body
Application in the Prototype Java JDK
- ArrayList
- HashMap
Advantages of the prototype pattern
- Excellent performance. Java’s own prototype mode is based on the copy of in-memory binary stream, which is much better than directly new an object
- You can store the state of an object using deep cloning. You can use prototype mode to make a copy of an object and store its state, simplifying the creation process and eliminating the need to repeatedly set parameters through constructors or get\set methods
Disadvantages of the prototype pattern
- Clone (or copiable) methods must be equipped
- When modifying an existing class, you need to modify the code, which violates the open close principle
- Deep copy and shallow copy must be used properly
- Use of stereotype and singleton requirements separately (a class cannot be both a singleton and a stereotype)
The difference between deep clone and shallow clone
- A deep clone copies values
- Shallow clones copy references
The prototype
- example
A prototype object
import lombok.Data; @Data public class ExamPaper{ private String examinationPaperId; // Private String leavTime; Private String organizationId; Private String ID; Private String examRoomId; Private String userId; Private String specialtyCode; // Private String postionCode; Private String gradeCode; Private String examStartTime; // Test start time private String examEndTime; Private String singleSelectionImpCount; Private String multiSelectionImpCount; Private String judgementImpCount; // Private String examTime; Private String fullScore; // Private String passScore; // private String userName; // Private String score; Private String resut; Private String singleOkCount; Private String multiOkCount; // Number of multiple choice questions answered private String judgementOkCount; Public ExamPaper copy(){ExamPaper ExamPaper = new ExamPaper(); Exampaper.setleavtime (this.getleavtime ()); // Exampaper.setleavtime (this.getleavtime ()); / / unit of the primary key examPaper. SetOrganizationId (enclosing getOrganizationId ()); // exampaper.setid (this.getid ()); // Exampaper.setUserId (this.getUserId()); / / professional examPaper. SetSpecialtyCode (enclosing getSpecialtyCode ()); / / post examPaper. SetPostionCode (enclosing getPostionCode ()); / / level examPaper. SetGradeCode (enclosing getGradeCode ()); / / start time examPaper exam. SetExamStartTime (enclosing getExamStartTime ()); Exampaper.setexamendtime (this.getExamendTime ()); / / single topic selection important quantity examPaper. SetSingleSelectionImpCount (enclosing getSingleSelectionImpCount ()); / / multiple choice important quantity examPaper. SetMultiSelectionImpCount (enclosing getMultiSelectionImpCount ()); / / determine the topic important quantity examPaper. SetJudgementImpCount (enclosing getJudgementImpCount ()); Exampaper.setexamtime (this.getexamtime ())); // Exampaper.setexamtime (this.getexamtime ()); / / total examPaper. SetFullScore (enclosing getFullScore ()); Exampaper.setpassscore (this.getPassScore())); Exampaper.setusername (this.getUsername ())); / / score examPaper. SetScore (enclosing getScore ()); / / radio right quantity examPaper. SetSingleOkCount (enclosing getSingleOkCount ()); / / a multiple-choice answer number examPaper. SetMultiOkCount (enclosing getMultiOkCount ()); / / judgment right quantity examPaper. SetJudgementOkCount (enclosing getJudgementOkCount ()); return examPaper; } @Override public String toString() { return "ExamPaper{" + "examinationPaperId='" + examinationPaperId + '\'' + ", leavTime='" + leavTime + '\'' + ", organizationId='" + organizationId + '\'' + ", id='" + id + '\'' + ", examRoomId='" + examRoomId + '\'' + ", userId='" + userId + '\'' + ", specialtyCode='" + specialtyCode + '\'' + ", postionCode='" + postionCode + '\'' + ", gradeCode='" + gradeCode + '\'' + ", examStartTime='" + examStartTime + '\'' + ", examEndTime='" + examEndTime + '\'' + ", singleSelectionImpCount='" + singleSelectionImpCount + '\'' + ", multiSelectionImpCount='" + multiSelectionImpCount + '\'' + ", judgementImpCount='" + judgementImpCount + '\'' + ", examTime='" + examTime + '\'' + ", fullScore='" + fullScore + '\'' + ", passScore='" + passScore + '\'' + ", userName='" + userName + '\'' + ", score='" + score + '\'' + ", resut='" + resut + '\'' + ", singleOkCount='" + singleOkCount + '\'' + ", multiOkCount='" + multiOkCount + '\'' + ", judgementOkCount='" + judgementOkCount + '\'' + '}'; }}Copy the code
BeanUtils copies objects because they have a lot of properties and uses reflection to assign values.
import java.lang.reflect.Field; public class BeanUtils { public static Object copy(Object protorype) { Class clazz = protorype.getClass(); Object returnValue = null; try { returnValue = clazz.newInstance(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); field.set(returnValue, field.get(protorype)); } }catch (Exception e){ e.printStackTrace(); } return returnValue; }}Copy the code
Client testing
public class Client { public static void main(String[] args) { // ExamPaper examPaper = new ExamPaper(); // System.out.println(examPaper); ExamPaper examPaper = (ExamPaper)BeanUtils.copy(new ExamPaper()); System.out.println(examPaper); }}Copy the code
First, shallow clone
- Conclusion: Hobbies refer to data types, shallow clones that copy prototype object values. They are the same reference and do not generate new objects
@Data public class ConcretePrototype implements Cloneable { private int age; private String name; private List<String> hobbies; @Override public ConcretePrototype clone() { try { return (ConcretePrototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } @Override public String toString() { return "ConcretePrototype{" + "age=" + age + ", name='" + name + '\'' + ", hobbies=" + hobbies + '}'; }}Copy the code
Public Class Client {public static void main(String[] args) {// ConcretePrototype prototype = new ConcretePrototype(); prototype.setAge(18); prototype.setName("Lisa"); List<String> hobbies = new ArrayList<>(); Hobbies. Add (" music "); Hobbies. Add (" fine arts "); prototype.setHobbies(hobbies); ConcretePrototype cloneType = prototype.clone(); CloneType. GetHobbies (). The add (" basketball "); System.out.println(" prototype: "+ prototype); System.out.println(" clone object: "+ cloneType); System.out.println(prototype == cloneType); System.out.println(" prototype.gethobbies () "); Println (" clone object hobby: "+ clonetype.gethobbies ()); System.out.println(prototype.getHobbies() == cloneType.getHobbies()); }}Copy the code
Second, deep cloning
@Data public class ConcretePrototype implements Cloneable,Serializable { private int age; private String name; private List<String> hobbies; @Override public ConcretePrototype clone() { try { return (ConcretePrototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } public ConcretePrototype 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); return (ConcretePrototype) ois.readObject(); } catch (Exception e) { e.printStackTrace(); return null; } } @Override public String toString() { return "ConcretePrototype{" + "age=" + age + ", name='" + name + '\'' + ", hobbies=" + hobbies + '}'; }}Copy the code
import java.util.ArrayList; import java.util.List; Public Class Client {public static void main(String[] args) {// ConcretePrototype prototype = new ConcretePrototype(); prototype.setAge(18); prototype.setName("Lisa"); List<String> hobbies = new ArrayList<>(); Hobbies. Add (" music "); Hobbies. Add (" fine arts "); prototype.setHobbies(hobbies); // ConcretePrototype cloneType = prototype. DeepClone (); CloneType. GetHobbies (). The add (" basketball "); System.out.println(" prototype: "+ prototype); System.out.println(" clone object: "+ cloneType); System.out.println(prototype == cloneType); System.out.println(" prototype.gethobbies () "); Println (" clone object hobby: "+ clonetype.gethobbies ()); System.out.println(prototype.getHobbies() == cloneType.getHobbies()); }}Copy the code
Execution Result:
The singleton
import lombok.Data; import java.util.List; @Data public class ConcretePrototype implements Cloneable { private int age; private String name; private List<String> hobbies; private static ConcretePrototype instance = new ConcretePrototype(); private ConcretePrototype(){} public static ConcretePrototype getInstance(){ return instance; } @Override public ConcretePrototype clone() { try { return (ConcretePrototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } @Override public String toString() { return "ConcretePrototype{" + "age=" + age + ", name='" + name + '\'' + ", hobbies=" + hobbies + '}'; }}Copy the code
import java.util.ArrayList; import java.util.List; Public Class Client {public static void main(String[] args) {// ConcretePrototype prototype = ConcretePrototype.getInstance(); prototype.setAge(18); prototype.setName("Lisa"); List<String> hobbies = new ArrayList<>(); Hobbies. Add (" music "); Hobbies. Add (" fine arts "); prototype.setHobbies(hobbies); ConcretePrototype cloneType = prototype.clone(); CloneType. GetHobbies (). The add (" basketball "); System.out.println(" prototype: "+ prototype); System.out.println(" clone object: "+ cloneType); System.out.println(prototype == cloneType); System.out.println(" prototype.gethobbies () "); Println (" clone object hobby: "+ clonetype.gethobbies ()); System.out.println(prototype.getHobbies() == cloneType.getHobbies()); }}Copy the code
- Do not implement the Cloneable interface if it is singleton mode
- If implemented, the clone method is as follows
@Override
public ConcretePrototype clone() {
return instance;
}
Copy the code
- The stereotype and singleton patterns conflict and you can only choose one or the other