"Crazy learning of Java design patterns: prototype patterns"
Mode type
The prototype pattern belongs to the creation pattern, which provides the best way to create objects.
Two, schema definition
- Q: what is a prototype model?
- Answer:
- Prototype Pattern is to use prototype instances to specify the type of objects to be created, and create new objects by copying these prototypes; In fact, it is the process mode of creating repeated objects on the premise of ensuring performance.
- The prototype pattern implements a prototype interface, which is used to create a clone of the current object. This pattern is used when the cost of directly creating objects is relatively high.
- For example, an object needs to be created after a costly database operation. We can cache the object, return its clone on the next request, and update the database when necessary, so as to reduce database calls.
Three, mode implementation
1. Example background
We are all very familiar with the background of journey to the West
We all liked the monkey king when we were young. He pulled out a hair and blew out thousands of monkeys, which is the prototype model
The monkey is the basic prototype
Monkey King is his extended prototype. It has more golden cudgel weapons than monkeys and implements Clonable interface and serialization interface
2. Code implementation
package com.gitee.qianpz.prototype.pattern; import java.util.Date; /** * @author pengzhan.qian * @since 1.0.0 */ public class Monkey { private Integer height; private Integer weight; private Date birthDay; public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } } package com.gitee.qianpz.prototype.pattern; import java.io.Serializable; /** * @author pengzhan.qian * @since 1.0.0 */ public class JinGuBang implements Serializable { private static final long serialVersionUID = -6725817841369486102L; private Integer length = 100; private Integer height = 10; public void big() { this.height *= 2; this.length *= 2; } public void small() { this.height /= 2; this.length /= 2; } public Integer getLength() { return length; } public void setLength(Integer length) { this.length = length; } public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } } package com.gitee.qianpz.prototype.pattern; import java.io.*; import java.util.Date; /** * @author pengzhan.qian * @since 1.0.0 */ public class Sunwukong extends Monkey implements Cloneable, Serializable { private static final long serialVersionUID = 1766323545640488986L; private JinGuBang jinGuBang; public JinGuBang getJinGuBang() { return jinGuBang; } public void setJinGuBang(JinGuBang jinGuBang) { this.jinGuBang = jinGuBang; } /** * initialization */ public Sunwukong() { this.setBirthDay(new Date()); this.jinGuBang = new JinGuBang(); } /** * Rewrite cloning method * This is deep cloning * * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { return this.deepClone(); } /** * Deep cloning * * @return */ private Sunwukong deepClone() { try { //The object is stored in memory, and the object is read and written through bytecode ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(this); // ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); Sunwukong copy = (Sunwukong) objectInputStream.readObject(); copy.setBirthDay(new Date()); objectInputStream.close(); byteArrayInputStream.close(); objectOutputStream.close(); byteArrayOutputStream.close(); return copy; } catch (Exception e) { e.printStackTrace(); return null; } } /** * Shallow cloning * * @param target * @return */ public Sunwukong shallowClone(Sunwukong target) { Sunwukong sunwukong = new Sunwukong(); sunwukong.setHeight(target.getHeight()); sunwukong.setWeight(target.getWeight()); sunwukong.setBirthDay(new Date()); sunwukong.setJinGuBang(target.jinGuBang); return sunwukong; } } package com.gitee.qianpz.prototype.pattern; /** * @author pengzhan.qian * @since 1.0.0 */ public class PrototypeTests { public static void main(String[] args) { //Deep cloning test //The content is consistent, but the memory address is inconsistent Sunwukong sunwukong = new Sunwukong(); try { Sunwukong deepCopy = (Sunwukong) sunwukong.clone(); System.out.println("Deep cloning==>" + (sunwukong.getJinGuBang() == deepCopy.getJinGuBang())); } catch (Exception e) { e.printStackTrace(); } //Shallow clone test //The contents are the same and the memory address is the same. A change will affect the clone object Sunwukong sunwukong1 = new Sunwukong(); Sunwukong sunwukong2 = sunwukong1.shallowClone(sunwukong1); System.out.println("Shallow cloning==>" + (sunwukong1.getJinGuBang() == sunwukong2.getJinGuBang())); } }
4, Prototype model summary
1. Advantages
- Performance improvement
- The caller does not need to know any details about the creation of the original object, nor does he call the constructor of the original object, avoiding the constraints of the constructor
2. Shortcomings
- It is not very difficult for a new class, but it is not necessarily easy for an existing class, especially when a class references an indirect object that does not support serialization, or when the reference contains a circular structure.
- Clonable interface must be implemented.
3. Usage scenario
- 1. Resource optimization scenario.
- 2. Class initialization needs to digest a lot of resources, including data, hardware resources, etc.
- 3. Scenarios with performance and safety requirements.
- 4. If generating an object through new requires very cumbersome data preparation or access rights, you can use the prototype pattern.
- 5. A scene where one object has multiple modifiers.
- 6. When an object needs to be accessed by other objects, and each caller may need to modify its value, you can consider using the prototype pattern to copy multiple objects for the caller to use.
- 7. In actual projects, the prototype pattern rarely appears alone. It usually appears together with the factory method pattern. An object is created through the clone method, and then provided to the caller by the factory method. The prototype pattern has been integrated with Java, and you can use it easily.
4. Core code
- 1. Implement cloning operation, inherit clonable in JAVA and rewrite clone()
- 2. The prototype pattern is also used to isolate the coupling relationship between the users of class objects and specific types (mutable classes). It also requires these "mutable classes" to have stable interfaces.
- 3. The core of deep cloning is serialization and deserialization