配置网站开发,建筑网招工网,锡林郭勒建站,wordpress标签页面添加自定义字段概念#xff1a;
原型模式 (Prototype Pattern)是一种创建型设计模式#xff0c;它允许通过复制现有对象来创建新对象#xff0c;而无需依赖于昂贵的实例化过程。该模式基于原型实例生成新的对象#xff0c;并且可以根据需要进行修改和定制。
特点#xff1a;
通过克隆…概念
原型模式 (Prototype Pattern)是一种创建型设计模式它允许通过复制现有对象来创建新对象而无需依赖于昂贵的实例化过程。该模式基于原型实例生成新的对象并且可以根据需要进行修改和定制。
特点
通过克隆已有对象来创建新对象避免了重复的初始化过程。可以动态地添加或删除已有的原型。提供了一种简单、灵活和高效的方式来创建多个相似对象。
优点
减少了重复代码提高了代码复用性。避免了耗时的实例化操作提升性能。简化了对象创建过程使得系统更加灵活。
缺点
需要为每个可变属性添加适当的克隆方法并在每次修改时更新这些方法。如果存在循环引用则需要小心处理克隆过程中可能出现的无限循环问题。
适用场景
当一个系统需要独立于其具体类型创建多个相似但不同配置项或版本时可以使用原型模式。当一个系统需要动态地加载和配置类实例时可以使用原型模式。
实现方式
浅拷贝
直接对目标对象进行浅拷贝复制基本数据类型的值和引用类型的地址。
实现原理
创建一个新对象并将原始对象中所有的字段值复制给新对象。对于基本数据类型直接进行值复制。对于引用类型只复制其地址而不创建新的实例。
实现代码:
import java.util.ArrayList;
import java.util.List;class Prototype implements Cloneable {private int id;private String name;private ListString list;// 构造函数public Prototype(int id, String name, ListString list) {this.id id;this.name name;this.list list;}// Getter 和 Setterpublic void setList(ListString list) {this.list list;}public ListString getList(){return this.list;}Overridepublic Prototype clone() throws CloneNotSupportedException {return (Prototype) super.clone();}
}public class Main {public static void main(String[] args) {ListString originalList new ArrayList();originalList.add(item1);originalList.add(item2);Prototype originalObject new Prototype(1, Original, originalList);try {Prototype clonedObject originalObject.clone();System.out.println(originalObject clonedObject); // 输出 falseSystem.out.println(originalObject.getList() clonedObject.getList()); // 输出 true} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}在上述示例中Prototype 类实现了 Cloneable 接口并重写了 clone() 方法。通过调用 super.clone() 进行浅拷贝操作返回一个新的克隆对象。
接下来我们创建了一个原始对象 originalObject并进行浅拷贝得到克隆对象 clonedObject。可以观察到两个对象不相等因为引用地址不同但是它们共享相同的引用类型字段即列表所以对列表的修改会同时影响两个对象。
存在问题由于浅拷贝仅仅是对引用进行了简单地复制操作并没有创建全新独立的副本因此可能会导致以下问题
如果被复制的引用类型发生改变那么克隆后得到的副本也会受到影响。在多层嵌套结构中如果某个属性发生改变则克隆后得到副本中对应属性也会改变。
深拷贝
对目标对象进行深拷贝复制基本数据类型的值和引用类型的整个对象。
实现原理
创建一个新对象并将原始对象中所有字段值复制给新对象。对于基本数据类型直接进行值复制。对于引用类型在克隆过程中创建该引用类型的全新副本并将副本赋值给新对象。
实现代码
import java.util.ArrayList;
import java.util.List;class Prototype implements Cloneable {private int id;private String name;private ListString list;// 构造函数public Prototype(int id, String name, ListString list) {this.id id;this.name name;this.list list;}// Getter 和 Setterpublic ListString getList() {return list;}public void setList(ListString list) {this.list list;}Overridepublic Prototype clone() throws CloneNotSupportedException {Prototype clonedObject (Prototype) super.clone();clonedObject.list new ArrayList(this.list); // 创建全新副本return clonedObject;}
}public class Main {public static void main(String[] args) {ListString originalList new ArrayList();originalList.add(item1);originalList.add(item2);Prototype originalObject new Prototype(1, Original, originalList);try {Prototype clonedObject originalObject.clone();System.out.println(originalObject clonedObject); // 输出 falseSystem.out.println(originalObject.getList() clonedObject.getList()); // 输出 false} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}在上述示例中Prototype 类实现了 Cloneable 接口并重写了 clone() 方法。通过调用 super.clone() 进行浅拷贝操作然后对引用类型字段进行深层次克隆。
接下来我们创建了一个原始对象 originalObject并进行深拷贝得到克隆对象 clonedObject。可以观察到两个对象完全独立因为引用地址不同它们的列表也是独立的副本所以对列表的修改不会相互影响。
深拷贝虽然解决了浅拷贝可能带来的问题但也存在以下问题
如果被复制的引用类型内部还包含其他引用类型则需要递归地进行深层次克隆操作。某些类可能无法被序列化或反序列化而导致无法使用标准方法实现深拷贝。
原型注册表
使用原型管理器来存储和获取原型实例可以通过名称或标识符查找并克隆相应的原型。
实现原理
创建一个原型注册表类通常为单例用于存储和管理多个不同类型的原型对象。在注册表中添加方法用于向注册表中添加、删除或获取指定名称的原型对象。当客户端需要创建新对象时可以通过调用注册表中相应名称的方法来获取对应的克隆副本。
实现代码
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;class Prototype implements Cloneable {private int id;private String name;private ListString list;// 构造函数public Prototype(int id, String name, ListString list) {this.id id;this.name name;this.list list;}// Getter 和 Setterpublic void setName(String name){this.name name;}public String getName() {return this.name;}public ListString getList() {return list;}public void setList(ListString list) {this.list list;}Overridepublic Prototype clone() throws CloneNotSupportedException {Prototype clonedObject (Prototype) super.clone();clonedObject.list new ArrayList(this.list); // 创建全新副本return clonedObject;}
}class PrototypeRegistry {private static PrototypeRegistry instance;private MapString, Prototype prototypes;private PrototypeRegistry() {prototypes new HashMap();}public static synchronized PrototypeRegistry getInstance() {if (instance null) {instance new PrototypeRegistry();}return instance;}public void addPrototype(String name, Prototype prototype) {prototypes.put(name, prototype);}public void removePrototype(String name) {prototypes.remove(name);}public Prototype getPrototype(String name) throws CloneNotSupportedException {Prototype prototype prototypes.get(name);if (prototype ! null) {return prototype.clone();}return null;}
}public class Main {public static void main(String[] args) {
// 创建原始对象并添加到注册表ListString originalList new ArrayList();originalList.add(item1);originalList.add(item2);Prototype originalObject new Prototype(1, Original, originalList);PrototypeRegistry registry PrototypeRegistry.getInstance();registry.addPrototype(object1, originalObject);// 从注册表获取副本并进行修改try {Prototype clonedObject registry.getPrototype(object1);if (clonedObject ! null) {clonedObject.setName(Cloned);System.out.println(originalObject.getName()); // 输出 OriginalSystem.out.println(clonedObject.getName()); // 输出 ClonedSystem.out.println(originalObject.getList() clonedObject.getList()); // 输出 false}} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}在深拷贝实现代码的基础上我们增加了PrototypeRegistry 类实现了原型注册表的功能。通过使用单例模式保证只有一个注册表实例并使用 HashMap 存储原型对象。然后创建了一个原始对象 originalObject 并将其添加到注册表中。然后通过调用 getPrototype() 方法从注册表中获取副本并对副本进行修改。可以观察到两个对象是独立的对一个对象的修改不会影响到另一个对象。
序列化与反序列化
将对象序列化为字节流然后再反序列化为新对象。
实现原理
被克隆的对象必须实现 Serializable 接口。序列化使用 ObjectOutputStream 将对象写入输出流并将其转换为字节数组。反序列化使用 ObjectInputStream 从输入流中读取字节数组并将其转换回原始对象。
实现代码
import java.io.*;
import java.util.ArrayList;
import java.util.List;class Prototype implements Serializable {private int id;private String name;private ListString list;// 构造函数public Prototype(int id, String name, ListString list) {this.id id;this.name name;this.list list;}// Getter 和 Setterpublic ListString getList() {return list;}public Prototype deepClone() {try {ByteArrayOutputStream baos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(baos);oos.writeObject(this);ByteArrayInputStream bais new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois new ObjectInputStream(bais);return (Prototype) ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return null;}
}public class Main {public static void main(String[] args) {ListString originalList new ArrayList();originalList.add(item1);originalList.add(item2);Prototype originalObject new Prototype(1, Original, originalList);Prototype clonedObject originalObject.deepClone();System.out.println(originalObject clonedObject); // 输出 falseSystem.out.println(originalObject.getList() clonedObject.getList()); // 输出 false}
}在上述示例中Prototype 类实现了 Serializable 接口并提供了一个 deepClone() 方法来进行深拷贝。在该方法中首先将对象写入输出流并转换为字节数组然后再从输入流中读取字节数组并转换回对象。然后我们创建了一个原始对象 originalObject 并通过调用 deepClone() 方法进行深拷贝得到副本对象 clonedObject。可以观察到两个对象是独立的因为引用地址不同它们的列表也是独立的副本所以对列表的修改不会相互影响。需要注意的是当被克隆的类包含不可被序列化或反序列化的字段如线程、文件句柄等则需要采取额外措施来处理这些字段。