跳到主要内容

原型模式

定义

原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制(克隆)现有对象来创建新对象,而不是通过实例化类来创建。这种方式可以避免创建对象时的复杂初始化过程

title='原型模式主要解决的问题'

如果创建对象的成本比较大,比如对象中的数据是经过复杂计算才能得到,或者需要从 RPC 接口或者数据库等比较慢的 IO 中获取,这种情况我们就可以使用原型模型,从其它已有的对象中进行拷贝,而不是每次都创建新对象,进行一些耗时的操作。

应用场景

原型模式主要适用于以下场景:

  1. 对象创建成本高

    • 需要大量计算或数据库访问
    • 需要复杂的初始化过程
  2. 对象包含其他对象的情况

    • 对象之间存在复杂的依赖关系
    • 需要维护对象的一致性
  3. 频繁创建相似对象

    • 需要创建大量相似但不完全相同的对象
    • 对象的差异仅在于其状态的不同

实现方式

浅克隆

克隆对象中的所有变量的值与原型对象的值完全相同(引用数据类型变量中存储的地址也是完全一致的)。

深克隆

克隆对象的所有基本数据类型变量含有的值与原型对象完全一致(不包含引用数据类型)。

基本实现

在 Java 中,可以通过实现 Cloneable 接口来实现原型模式:

public class Prototype implements Cloneable {
private String field;

public Prototype(String field) {
this.field = field;
}

@Override
public Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
}

深拷贝与浅拷贝

  1. 浅拷贝
    • 复制对象的基本类型字段
    • 复制对象引用,但不复制引用的对象
public class ShallowCopy implements Cloneable {
private int[] data;

@Override
public ShallowCopy clone() throws CloneNotSupportedException {
return (ShallowCopy) super.clone();
}
}
  1. 深拷贝
    • 复制对象的所有字段
    • 递归复制引用的对象
public class DeepCopy implements Cloneable {
private int[] data;

@Override
public DeepCopy clone() throws CloneNotSupportedException {
DeepCopy clone = (DeepCopy) super.clone();
clone.data = data.clone();
return clone;
}
}

最佳实践

  1. 注册原型
    • 维护一个原型注册表
    • 根据需要获取原型进行克隆
public class PrototypeManager {
private static Map<String, Prototype> prototypes = new HashMap<>();

public static void registerPrototype(String key, Prototype prototype) {
prototypes.put(key, prototype);
}

public static Prototype getPrototype(String key) throws CloneNotSupportedException {
Prototype prototype = prototypes.get(key);
return prototype.clone();
}
}
  1. 使用序列化实现深拷贝
    • 适用于复杂对象的深拷贝
    • 要求所有相关类都实现 Serializable 接口
public class SerializablePrototype implements Serializable {
public SerializablePrototype deepCopy() throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (SerializablePrototype) ois.readObject();
}
}

优缺点

优点

  1. 减少对象创建的开销
  2. 动态添加或删除产品
  3. 提供更灵活的实例化机制

缺点

  1. 需要为每个类实现克隆方法
  2. 深拷贝实现较为复杂
  3. 可能违反封装原则

实际应用示例

HashMap 的克隆

Java 中的 HashMap 就使用了原型模式:

public class HashMapExample {
public static void main(String[] args) {
HashMap<String, Integer> original = new HashMap<>();
original.put("A", 1);
original.put("B", 2);

// 克隆 HashMap
HashMap<String, Integer> clone = (HashMap<String, Integer>) original.clone();
clone.put("C", 3);

// 原始 Map 不受影响
System.out.println(original.size()); // 输出: 2
System.out.println(clone.size()); // 输出: 3
}
}