← 返回题目列表

什么是原型模式?它解决什么问题?

高频 简单 第 1 / 25 题 更新于 2026/07/28
原型模式创建型模式对象复制clone设计模式

简化版

原型模式是通过复制已有对象来创建新对象,而不是每次都从零开始 new 并初始化。它主要解决复杂对象创建成本高、初始化过程重复、对象结构相似但细节不同的问题。

详细版

原型模式的核心思想是:先准备一个原型对象,需要新对象时直接复制这个原型,再按需修改少量字段。

它适合这些情况:

  • 对象创建过程复杂;
  • 初始化成本高;
  • 对象之间大部分字段相同;
  • 想避免客户端知道复杂构造细节;
  • 运行时需要动态复制某类对象。

典型代码形态:

interface Prototype<T> {
    T copy();
}

客户端只需要调用:

OrderTemplate template = registry.get("normal");
OrderTemplate order = template.copy();

原型模式的重点不是“复制”这个动作本身,而是用复制来复用已有对象的初始化状态。

完整版教学

一、为什么需要原型模式

普通创建对象通常是:

Report report = new Report();
report.setTitle("月报");
report.setStyle(defaultStyle);
report.setColumns(defaultColumns);
report.setPermissions(defaultPermissions);

如果这些初始化步骤很多,而且每次创建都差不多,就会出现大量重复代码。

原型模式的思路是先准备好一个标准模板:

Report prototype = new Report();
prototype.initDefaultConfig();

之后创建新报表时复制它:

Report report = prototype.copy();
report.setTitle("7 月销售月报");

这样新对象能继承原型的默认配置,只修改差异部分。

二、原型模式属于创建型模式

创建型模式关注“对象怎么创建”。

工厂模式通过工厂方法创建对象,建造者模式通过步骤组装复杂对象,原型模式则通过复制已有对象创建对象。

它的创建入口不是构造器,而是:

已有对象 -> 复制 -> 新对象

这就是原型模式和其他创建型模式最明显的差别。

三、原型模式解决的是初始化复用

很多人以为原型模式只是 clone(),其实它真正复用的是对象状态。

例如一个游戏角色模板:

等级:1
职业:法师
初始技能:火球术、闪现
默认装备:新手法杖
属性成长曲线:法师成长模板

创建新角色时,不需要重新设置这些默认值,直接复制模板,再设置玩家名称即可。

四、复制出来的对象必须是新对象

原型模式不是共享同一个对象。

正确关系是:

prototype != copy

如果返回的是原对象本身,就会导致多个使用方互相修改同一个对象。

复制后,新对象应该拥有自己的身份和生命周期。

五、原型模式的难点在深浅拷贝

如果对象字段都是基本类型或不可变对象,复制比较简单。

但如果对象里有可变引用:

class Report {
    List<String> columns;
}

浅拷贝会让新旧对象共享同一个 columns 列表。一个对象修改列配置,另一个对象也会被影响。

这就是原型模式最容易出 bug 的地方。

六、常见误区与追问

原型模式的核心不是 Java clone(),而是以已有实例作为创建蓝本。若构造一个规则对象需解析500条配置,先完成1个标准原型后复制并覆盖少数字段,可以复用昂贵的初始化结果。前提是复制后对象身份独立,并且共享与独占字段都有明确约定。

检查维度判定依据
创建依据已有对象的状态
主要难点对象图复制与业务身份处理

记忆钩子:原型回答“照着哪个成品再做一个”,而不是“调用哪个构造器”。

  • 误区:实现 Cloneable 才算原型模式。 自定义 copy、拷贝构造器或序列化都可承载原型思想。
  • 追问:为什么它属于创建型模式? 它改变对象获得方式,用复制现有实例替代从零构造。
  • 误区:副本与原型字段必须完全相同。 复制后可以重置身份字段或覆盖配置,关键是初始蓝本被复用。
  • 追问:复制和引用赋值有什么区别? 引用赋值没有新对象,复制至少创建独立的顶层实例。
  • 追问:模式最危险的地方是什么? 未定义可变嵌套对象的共享边界,导致副本修改污染原型。

七、加强记忆

原型模式就是用“复制已有对象”来创建新对象。它适合对象初始化复杂、对象结构相似、默认配置很多的场景;真正难点不是调用复制方法,而是判断哪些字段可以共享、哪些可变对象必须深拷贝。