Writing in the front

  • Take notes on learning design patterns
  • Improve flexibility in the use of design patterns

Learning to address

https://www.bilibili.com/vide…

https://www.bilibili.com/vide…

Refer to the article

http://c.biancheng.net/view/1…

Project source https://gitee.com/zhuang-kang/DesignPattern

6. Prototype patterns

6.1 Definition and Characteristics of Prototype Schema

The Prototype pattern is defined as follows: Create a new object that is the same or similar to the Prototype by copying an already created instance as the Prototype. Here, the prototype instance specifies the type of object to be created. Creating objects in this way is very efficient, and you don’t need to know the details of object creation. For example, installation of the Windows operating system is usually time consuming, and replication is much faster.

Advantages of the prototype pattern:

  • Java’s native prototype pattern is based on copying in-memory binary streams, which is better at performance than directly new an object.
  • The ability to use deep cloning to save the state of an object, using the prototype mode to copy the object and save its state, simplifies the process of creating the object, so that it can be used when needed (such as reverting to a historical state), can assist in the implementation of undo operations.

Disadvantages of the prototype pattern:

  • You need to configure a Clone method for each class
  • The clone method sits inside a class, and when you modify an existing class, you need to modify the code, violating the Open Closed Principle.
  • When deep cloning is implemented, complex code needs to be written, and when there are multiple nested references between objects, in order to achieve deep cloning, the corresponding class of each layer of objects must support deep cloning, which is more troublesome to implement. Therefore, deep cloning, shallow cloning needs to be used properly.

6.2 Structure and implementation of the prototype pattern

6.2.1 Structure of the prototype schema

The archetypal pattern contains the following major actors.

  1. Abstract prototype classes: Specifies the interfaces that concrete prototype objects must implement.
  2. Concrete prototype class: Implementing the clone() method of the abstract prototype class, which is a copyable object.
  3. Access classes: Use the clone() method in the concrete prototype class to copy the new object.

6.2.2 Code implementation

Shallow clone: Creates a new object with the same properties as the original object. For non-primitive properties, it still points to the memory address of the object to which the original attribute points.

Deep clone: When a new object is created, other objects referenced in the property will be cloned and no longer refer to the original object address.

6.2.2.1 shallow copy

IdCard

package com.zhuang.prototype.shallowclone; /** * @className idCard * @description * @date 2021/3/19 12:16 * @created by dell */ public class idCard { private String id; public IdCard(String id) { this.id = id; } @Override public String toString() { return "IdCard{" + "id=" + id + '}'; }}

Person

package com.zhuang.prototype.shallowclone; /** * @ClassName Person * @Description Shallow copy * @Date 2021/3/19 12:17 * @Created by Dell */ public class Person implements Cloneable { private String name; private int age; private IdCard idCard; public Person() { } public Person(String name, int age, IdCard idCard) { this.name = name; this.age = age; this.idCard = idCard; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", idCard=" + idCard + ", idCard.hashCode=" + idCard.hashCode() + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}

PersonTest

package com.zhuang.prototype.shallowclone; /** * @ClassName personTest * @Description * @Date 2021/3/19 12:17 * @Created by Dell */ public class personTest {public static void main(String[] args) throws Exception {Person Person = new Person(" 10086", 20, new IDCard ("10086")); Person person1 = (Person) person.clone(); Person person2 = (Person) person.clone(); System.out.println(person); System.out.println(person1); System.out.println(person2); }}

We found that shallow copying can be accomplished by implementing implements Cloneable, the basic variable is value-passing clone, and the reference object IdCard is reference passing, which is not consistent with our object-oriented thought, every Person should have an independent IdCard, rather than sharing one. To solve this problem, we need to use deep cloning

6.2.2.2 Deep copy (first type)

IdCard

package com.zhuang.prototype.deepclone.one; /** * @ClassName idCard * @Description * @Date 2021/3/19 12:33 * @Created by Dell */  IdCard implements Cloneable { private String id; public IdCard(String id) { this.id = id; } public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public String toString() { return "IdCard{" + "id='" + id + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}

Person

package com.zhuang.prototype.deepclone.one; /** * @ClassName Person * @Description * @Date 2021/3/19 12:33 * @Created by Dell */ public class Person implements Cloneable { private String name; private int age; private IdCard idCard; public Person(String name, int age, IdCard idCard) { this.name = name; this.age = age; this.idCard = idCard; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } @Override public String toString() { return "Person{" + "personHashCode=" + this.hashCode() + ", name='" + name + '\'' + ", age=" + age + ", idCard=" + idCard + ", idCardHashCode=" + idCard.hashCode() + '}'; } // Deep clone needs to be implemented manually, In the Object reference is to realize the clone method @ Override protected Object clone () throws CloneNotSupportedException {/ / copies of complete basic data types Person = super.clone(); Person = super.clone(); Person = super.clone(); Person p = (Person) Person; IdCard idCard = (IdCard) p.getIdCard().clone(); // Implement your own clone p.tidCard (idCard); return p; }}

PersonTest

package com.zhuang.prototype.deepclone.one; import java.io.Serializable; /** * @ClassName personTest * @Description * @Date 2021/3/19 12:33 * @Created by Dell */ public class personTest Name = "name"; name = "name"; name = "name"; name = "name"; name = "name"; name = "name"; name = "name"; 20, new IdCard("10086")); Person person1 = (Person) person.clone(); Person person2 = (Person) person.clone(); System.out.println(person); System.out.println(person1); System.out.println(person2); }}

Using this method of deep cloning, the perfect solution when the data type to a reference type, only copy of the original reference object address instead of a new reference object references, but this implementation has the disadvantages of a large, need to clone method in each object, if the class is full of your own writing, the natural right, to implement the line, But it’s a bit of a hassle. However, if you are referring to a class from a third party and cannot modify the source code, this way, it is obviously impossible to achieve deep cloning

6.2.2.2 Deep Copy (Second Type)

IdCard

package com.zhuang.prototype.deepclone.two; /** * @ClassName idCard * @Description 2 * @Date 2021/3/19 12:33 * @Created by Dell */ / Serializable public class IdCard implements Serializable { private String id; public IdCard(String id) { this.id = id; } public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public String toString() { return "IdCard{" + "id='" + id + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}

Person

package com.zhuang.prototype.deepclone.two; import java.io.*; /** * @ClassName Person * @Description 2 * @Date 2021/3/19 12:33 * @Created by Dell */ public class Person implements Serializable { private String name; private int age; private IdCard idCard; public Person(String name, int age, IdCard idCard) { this.name = name; this.age = age; this.idCard = idCard; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } @Override public String toString() { return "Person{" + "personHashCode=" + this.hashCode() + ", name='" + name + '\'' + ", age=" + age + ", idCard=" + idCard + ", idCardHashCode=" + idCard.hashCode() + '}'; } public Person DeelClone () {// create the stream object byteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; Try {// serialize BOS = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); // deserialize bis = new ByteArrayInputStream(BOS.toByteArray ()); ois = new ObjectInputStream(bis); return (Person) ois.readObject(); } catch (Exception e) { e.printStackTrace(); return null; } finally { try { ois.close(); bis.close(); oos.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); }}}}

PersonTest

package com.zhuang.prototype.deepclone.two; /** * @ClassName personTest * @Description * @Date 2021/3/19 12:33 * @Created by Dell */ public class personTest {public static void main(String[] args) throws Exception {public static void main(String[] args) throws Exception {public static void main(String[] args) throws Exception {public static void main(String[] args) throws Exception { new IdCard("10086")); Person person1 = (Person) person.deelClone(); Person person1 = (Person) person.deelClone(); Person person1 = (Person) person.deelClone(); Person person2 = (Person) person.deelClone(); System.out.println(" Deep copy (second way to implement the serialization interface)"); Println (person); println(person); println(person); System.out.println(person1); System.out.println(person2); }}

This way we need to manually write the DeepClone method and implement the deepClone using serialization and deserialization in the Java stream, but this implementation needs to inherit the serialized Serializable interface in every class. This way, if you are calling a third party class, It is also possible that a third party class does not implement the Serializable Serializable interface, but in general, most do. In general, this comparison is recommended and efficient

6.3 Application scenarios of the prototype pattern

  • Objects are the same or similar, that is, only a few individual properties are different.
  • The cost of creating objects is large, such as long initialization time, too much CPU, or too much network resources, so resources need to be optimized.
  • Creating an object requires tedious data preparation or access rights, etc., to improve performance or security.
  • This class of object is heavily used in the system, and each caller needs to reassign its properties.
  • In Spring, the prototype pattern is widely used. For example, scope=’prototype’, json.parseObject (), etc., are all specific applications of the prototype pattern.

6.4 Considerations and details of the prototype pattern

  • When creating new objects is complex, you can use the prototyping pattern to simplify the object creation process and increase efficiency
  • Obtain the runtime state of an object dynamically without reinitializing it
  • If the original object changes (adding or subtracting attributes), the other cloned objects change accordingly, without modifying the code

Write in the last

  • If my article is useful to you, please click 👍, thank you!
  • Let me know in the comments section if you have any questions! 💪