原型模式核心是复制持有状态的对象实例而非变量,Java中通过clone()实现,需区分浅克隆(引用共享)与深克隆(完全独立),适用字段多、初始化重、需快照等场景。

原型模式在变量状态复制中,核心不是“复制变量”,而是复制持有状态的对象实例。Java 中没有“变量的原型模式”这种说法,但你可以把一个封装了多个字段(即状态)的对象当作原型,用 clone() 快速生成新实例,保留当前全部字段值,避免重复 set 或构造。关键在于:状态要可克隆、引用要隔离、使用要明确。
明确哪些对象适合当原型
适合克隆的对象通常具备以下特征:
- 字段较多,手动 new + set 成本高(比如含 width/height/color/fontSize 等 5 个以上属性的 UI 组件)
- 创建依赖外部资源(如数据库查询、IO 初始化),但状态稳定,可缓存后复用
- 运行时动态调整过字段值,需要保留此刻快照用于后续分支操作(如表单暂存、配置回滚)
- 不频繁修改类结构,否则每个新增字段都需同步更新 clone 逻辑
浅克隆:快速但小心引用共享
直接调用 super.clone() 得到浅克隆,基本类型和 String 值被复制,但数组、集合、自定义对象等引用仍指向原对象内存地址。
例如:
public class Config implements Cloneable {private String env = "prod";
private List
@Override
protected Config clone() throws CloneNotSupportedException {
return (Config) super.clone(); // features 引用未变
}
}
⚠️ 若后续对 cloned.features.add("monitor"),原对象的 features 列表也会变化 —— 这不是预期行为。
深克隆:真正独立的状态副本
确保所有嵌套对象也被复制,常用两种方式:
- 手动递归克隆:在 clone 方法里对每个引用字段调用其自身的 clone()(要求它们也支持克隆)
-
序列化反序列化(推荐用于复杂嵌套):
将对象写入字节数组再读出,天然实现全量深拷贝,无需关心字段类型。
只需类实现Serializable,且无不可序列化字段(如 Socket、Thread)即可。
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
return (Config) ois.readObject();
}
实战建议:别只盯着 clone,用对时机
不是所有状态复制都需要原型模式:
- 简单 POJO 且字段少 → 直接构造器或 Builder 更清晰
- 状态需校验或转换 → clone 后再 set 比硬编码 clone 逻辑更可控
- 高频克隆 + 多层引用 → 优先用序列化深克隆,省去维护引用字段 clone 的成本
- 想统一管理多个原型 → 加一层 PrototypeRegistry,用 Map 缓存 key→prototype,按需取用并克隆










