Java创建型模式---原型模式
原型模式基础概念
原型模式是一种创建型设计模式,其核心思想是通过复制(克隆)现有对象来创建新对象,而无需依赖显式的类实例化过程。这种模式适用于创建对象成本较高(如初始化时间长、资源消耗大)或需要避免复杂的对象创建逻辑的场景。
原型模式的核心组件
- 原型接口 (Prototype) - 定义克隆方法的接口
- 具体原型类 (ConcretePrototype) - 实现原型接口,提供克隆方法的具体实现
- 客户端 (Client) - 通过调用原型对象的克隆方法来创建新对象
浅克隆与深克隆
在 Java 中,克隆分为两种类型:
浅克隆 (Shallow Clone) - 复制对象时,仅复制对象本身及其基本数据类型字段,而引用类型字段仍指向原对象的引用
- 深克隆 (Deep Clone) - 复制对象时,不仅复制对象本身,还递归复制其引用类型字段,确保新对象和原对象完全独立
原型模式的实现
下面通过示例代码展示原型模式的实现:
import java.util.ArrayList;
import java.util.List;// 原型接口
interface Prototype {Prototype clone();
}// 具体原型类 - 浅克隆示例
class Employee implements Prototype, Cloneable {private String name;private int age;private List<String> skills; // 引用类型字段public Employee(String name, int age, List<String> skills) {this.name = name;this.age = age;this.skills = skills;}// Getters and setterspublic 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 List<String> getSkills() {return skills;}public void setSkills(List<String> skills) {this.skills = skills;}// 浅克隆实现@Overridepublic Employee clone() {try {// 调用Object类的clone()方法进行浅克隆Employee cloned = (Employee) super.clone();return cloned;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", skills=" + skills +'}';}
}// 具体原型类 - 深克隆示例
class Department implements Prototype, Cloneable {private String deptName;private Employee manager; // 引用类型字段public Department(String deptName, Employee manager) {this.deptName = deptName;this.manager = manager;}// Getters and setterspublic String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public Employee getManager() {return manager;}public void setManager(Employee manager) {this.manager = manager;}// 深克隆实现@Overridepublic Department clone() {try {// 调用Object类的clone()方法进行浅克隆Department cloned = (Department) super.clone();// 手动深克隆引用类型字段if (this.manager != null) {// 递归克隆manager对象Employee clonedManager = this.manager.clone();// 为避免无限递归,需要在Employee类中实现深克隆// 这里假设Employee类已经正确实现了深克隆cloned.manager = clonedManager;}return cloned;} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}@Overridepublic String toString() {return "Department{" +"deptName='" + deptName + '\'' +", manager=" + manager +'}';}
}// 原型管理器 - 集中管理原型对象
class PrototypeManager {private static final java.util.Map<String, Prototype> prototypes = new java.util.HashMap<>();static {// 初始化一些原型对象List<String> skills = new ArrayList<>();skills.add("Java");skills.add("Spring");Employee employeePrototype = new Employee("Prototype Employee", 30, skills);prototypes.put("employee", employeePrototype);Department deptPrototype = new Department("IT Department", employeePrototype);prototypes.put("department", deptPrototype);}// 获取原型对象的克隆public static Prototype getClone(String key) {Prototype prototype = prototypes.get(key);if (prototype != null) {return prototype.clone();}return null;}// 注册新的原型对象public static void registerPrototype(String key, Prototype prototype) {prototypes.put(key, prototype);}
}// 客户端代码
public class PrototypePatternClient {public static void main(String[] args) {// 使用原型管理器获取克隆对象Employee clonedEmployee = (Employee) PrototypeManager.getClone("employee");Department clonedDepartment = (Department) PrototypeManager.getClone("department");System.out.println("Original Employee: " + PrototypeManager.getClone("employee"));System.out.println("Cloned Employee: " + clonedEmployee);System.out.println("\nOriginal Department: " + PrototypeManager.getClone("department"));System.out.println("Cloned Department: " + clonedDepartment);// 验证浅克隆和深克隆的效果// 修改克隆对象的基本类型字段clonedEmployee.setAge(35);// 修改克隆对象的引用类型字段List<String> clonedSkills = clonedEmployee.getSkills();clonedSkills.add("Hibernate");System.out.println("\nAfter modification:");System.out.println("Original Employee: " + PrototypeManager.getClone("employee"));System.out.println("Cloned Employee: " + clonedEmployee);// 验证深克隆Employee clonedManager = clonedDepartment.getManager();clonedManager.setName("New Manager");System.out.println("\nAfter manager modification:");System.out.println("Original Department Manager: " + ((Department) PrototypeManager.getClone("department")).getManager().getName());System.out.println("Cloned Department Manager: " + clonedDepartment.getManager().getName());}
}
原型模式的应用场景
- 对象创建成本高 - 当对象创建过程复杂或耗时较长时
- 避免重复初始化 - 当需要创建多个相同或相似的对象时
- 动态配置对象 - 当系统需要从现有对象动态生成新对象时
- 缓存原型对象 - 当需要缓存对象状态并在需要时恢复时
原型模式的优缺点
优点:
- 提高性能 - 避免重复创建对象的开销
- 简化对象创建 - 无需了解对象创建的具体细节
- 扩展性好 - 可以在运行时动态添加或删除原型
- 简化复杂对象创建 - 适合创建复杂配置的对象
缺点:
- 实现复杂 - 深克隆的实现可能比较复杂
- 克隆方法维护困难 - 当类的结构发生变化时,需要修改克隆方法
- 对克隆方法的依赖 - 必须实现 Cloneable 接口并重写 clone () 方法
使用原型模式的注意事项
- 正确实现克隆方法 - 确保浅克隆和深克隆的正确实现
- 处理引用类型字段 - 在深克隆中,需要递归克隆所有引用类型字段
- 考虑线程安全 - 如果在多线程环境中使用,需要考虑克隆方法的线程安全性
- 原型管理器的使用 - 对于复杂系统,考虑使用原型管理器集中管理原型对象
- 替代方案 - 在某些情况下,可以考虑使用序列化和反序列化实现深克隆
原型模式是一种非常实用的设计模式,它通过复制现有对象来创建新对象,避免了复杂的对象创建过程,提高了性能和灵活性。在实际开发中,根据对象的复杂度和需求,可以选择浅克隆或深克隆来实现原型模式。