​原型模式(Prototype Pattern)​​

定义

原型模式是一种​​创建型设计模式​​,通过复制现有对象(原型)来创建新对象,避免重复执行耗时的初始化操作。核心思想是​​以复制代替构造​​,特别适用于创建成本高的对象。


UML 类图​

设计模式之创建型:原型模式_设计模式

核心角色

  • Prototype:抽象原型接口,声明克隆方法(如 clone())。
  • ConcretePrototype:具体原型类,实现克隆逻辑(支持深拷贝或浅拷贝)。
  • Client:客户端,通过复制原型对象创建新实例。

优点​

  • 性能优化​​:避免重复执行耗时的初始化代码(如数据库连接、复杂计算)。
  • ​​动态创建对象​​:运行时通过克隆生成新对象,无需依赖具体类。
  • ​​简化对象创建​​:隐藏对象创建细节,客户端仅需调用 clone()。
  • ​​支持状态保存与恢复​​:可通过克隆快速生成对象的历史状态副本。

缺点​​

  • 深拷贝复杂度高​​:若对象包含嵌套引用,需递归处理所有层级,增加实现复杂度。
  • ​​需实现克隆方法​​:每个类需重写 clone(),可能违反开闭原则(需修改已有类)。
  • ​​循环引用问题​​:若对象间存在循环引用,深拷贝可能导致栈溢出或逻辑错误。

适用场景​

​创建成本高的对象​​

  • 数据库连接对象(避免重复建立连接)。
  • 复杂计算结果的缓存副本(如机器学习模型参数)。
    ​​## 动态生成对象​​
  • 游戏中的敌人复制(快速生成相同属性的敌人)。
  • 图形编辑器中的图形元素复制(如复制一个已配置的按钮)。
    ​​## 状态保存与回滚​​
  • 文本编辑器的撤销操作(克隆并保存文档状态)。
  • 事务操作的回滚点(克隆并暂存数据库状态)。
    ​​## 替代继承的扩展方式​​
  • 通过组合原型对象动态配置新对象,避免子类爆炸。

浅拷贝实现​

// 实现 Cloneable 接口(标记可克隆)
class ConcretePrototype implements Cloneable {
    private String field;
    private List<String> list = new ArrayList<>(); // 引用类型(浅拷贝会共享)

    public void setField(String field) { this.field = field; }
    public String getField() { return field; }
    public void addListItem(String item) { list.add(item); }

    @Override
    public ConcretePrototype clone() {
        try {
            return (ConcretePrototype) super.clone(); // 浅拷贝(默认 Object.clone() 是浅拷贝)
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 不会发生
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setField("原始值");
        prototype.addListItem("Item1");

        ConcretePrototype clone = prototype.clone();
        clone.setField("克隆值");
        clone.addListItem("Item2");

        System.out.println(prototype.getField()); // 输出: 原始值
        System.out.println(clone.getField());      // 输出: 克隆值
        System.out.println(prototype.list.size()); // 浅拷贝共享引用,输出: 2(Item1 和 Item2)
    }
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

深拷贝实现​

class DeepConcretePrototype implements Cloneable {
    private String field;
    private List<String> list = new ArrayList<>();

    public void setField(String field) { this.field = field; }
    public String getField() { return field; }
    public void addListItem(String item) { list.add(item); }

    @Override
    public DeepConcretePrototype clone() {
        try {
            DeepConcretePrototype clone = (DeepConcretePrototype) super.clone();
            clone.list = new ArrayList<>(this.list); // 手动深拷贝引用类型
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        DeepConcretePrototype prototype = new DeepConcretePrototype();
        prototype.addListItem("Item1");

        DeepConcretePrototype clone = prototype.clone();
        clone.addListItem("Item2");

        System.out.println(prototype.list.size()); // 输出: 1(深拷贝不共享引用)
        System.out.println(clone.list.size());     // 输出: 2
    }
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

​​原型管理器(扩展)​​

class PrototypeRegistry {
    private Map<String, Prototype> prototypes = new HashMap<>();

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

    public Prototype getClone(String key) {
        Prototype prototype = prototypes.get(key);
        return prototype != null ? prototype.clone() : null;
    }
}

// 使用示例
PrototypeRegistry registry = new PrototypeRegistry();
registry.addPrototype("default", new ConcretePrototype());

ConcretePrototype clone = (ConcretePrototype) registry.getClone("default");
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

​​总结​​:原型模式是优化对象创建性能的有效手段,尤其适用于需要频繁创建复杂对象的场景,但需谨慎处理深拷贝问题。