文章目录
-
- [1. 引言:为什么不直接 new?](#1. 引言:为什么不直接 new?)
- [2. 什么是原型模式](#2. 什么是原型模式)
-
- [GoF 定义](#GoF 定义)
- [3. 原型模式的核心思想](#3. 原型模式的核心思想)
- [4. 原型模式的角色组成](#4. 原型模式的角色组成)
- [5. Java 中的原型模式基础:Cloneable](#5. Java 中的原型模式基础:Cloneable)
- [6. 示例场景:文档模板复制](#6. 示例场景:文档模板复制)
- [7. 客户端使用](#7. 客户端使用)
- [8. 浅拷贝 vs 深拷贝(重点)](#8. 浅拷贝 vs 深拷贝(重点))
-
- [8.1 浅拷贝(Shallow Copy)](#8.1 浅拷贝(Shallow Copy))
- [8.2 深拷贝(Deep Copy)](#8.2 深拷贝(Deep Copy))
- [8.3 深拷贝的常见方式](#8.3 深拷贝的常见方式)
- [9. 原型模式的优点](#9. 原型模式的优点)
- [10. 原型模式的缺点](#10. 原型模式的缺点)
- [11. 适用场景](#11. 适用场景)
- [12. 原型模式在实际项目中的应用](#12. 原型模式在实际项目中的应用)
- [13. 原型模式的一个重要提醒](#13. 原型模式的一个重要提醒)
- 参考

1. 引言:为什么不直接 new?
在日常开发中,我们创建对象通常是这样的:
java
MyObject obj = new MyObject();
但在某些场景下,创建一个对象并不"简单":
- 对象初始化过程复杂
- 需要访问数据库、配置文件或远程服务
- 创建成本高、耗时长
- 对象状态相似,仅少量字段不同
如果每次都通过 new 完整构建对象,会带来明显的性能开销。
这时,一个问题出现了:
能不能通过"复制"已有对象来创建新对象?
答案就是------原型模式(Prototype Pattern)。
原型模式解决的核心问题是:
如何在创建成本高的前提下,高效地生成相似对象。
2. 什么是原型模式
GoF 定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
一句话理解:
通过 clone 一个已有对象,来生成新对象,而不是重新 new。
3. 原型模式的核心思想
原型模式的核心是两个字:
拷贝
与工厂模式"关注如何创建对象"不同,原型模式关注的是:
- 如何高效地复制对象
- 如何避免复杂初始化过程
4. 原型模式的角色组成
原型模式通常包含三个角色:
- 抽象原型类(Prototype):规定了具体原型对象必须实现的的 clone() 方法。
- 具体原型类(ConcretePrototype):实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类(Client):使用具体原型类中的 clone() 方法来复制新的对象。
结构非常简单:

5. Java 中的原型模式基础:Cloneable
Java 对原型模式提供了语言级支持:
Cloneable接口
在Cloneable 接口中并没有声明任何方法。它只是被用来标记可以使用clone方法进行复制的。这样的接口被称为标记接口(marker interface),如下图。

Object.clone()方法
使用方法:
- super:调用父类(Object 类)的 clone() 方法
- clone():Object 类中定义的本地(native)方法
- 整体意思是:"调用 Object 父类的 clone 方法进行浅拷贝"
6. 示例场景:文档模板复制
假设我们有一个文档对象,初始化过程非常复杂:
java
public class Document implements Cloneable {
private String title;
private String content;
public Document(String title, String content) {
// 模拟复杂初始化
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {}
this.title = title;
this.content = content;
}
@Override
protected Document clone() {
try {
return (Document) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
注意:
- Cloneable 是标记接口,没有任何方法
- clone() 方法定义在 Object 类中,是 protected 方法
- super 永远指向父类,接口不是父类
7. 客户端使用
java
public class Client {
public static void main(String[] args) {
Document prototype = new Document("模板", "初始内容");
Document copy1 = prototype.clone();
Document copy2 = prototype.clone();
}
}
效果:
- 原型只初始化一次
- 后续对象通过复制生成
- 性能显著提升
8. 浅拷贝 vs 深拷贝(重点)
这是原型模式中最容易出问题的地方。
8.1 浅拷贝(Shallow Copy)
只复制对象本身,引用类型字段仍指向同一对象。
java
public class Prototype implements Cloneable {
private List<String> list;
@Override
protected Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
}
问题:
- 修改一个对象的 list
- 所有 clone 出来的对象都会受影响
8.2 深拷贝(Deep Copy)
不仅复制对象本身,还复制其内部引用对象。
java
@Override
protected Prototype clone() throws CloneNotSupportedException {
Prototype copy = (Prototype) super.clone();
copy.list = new ArrayList<>(this.list);
return copy;
}
8.3 深拷贝的常见方式
- 手动 clone(最安全)
- 序列化 / 反序列化
- JSON 转换(不推荐用于高性能场景)
9. 原型模式的优点
- 提高性能
- 避免复杂初始化
- 动态创建对象
- 简化工厂类结构
10. 原型模式的缺点
- clone 实现复杂
- 深拷贝容易出错
- 破坏封装性
- 对象结构复杂时维护成本高
11. 适用场景
适合使用
- 创建对象成本高
- 对象差异小
- 需要大量相似对象
- 原型实例较稳定
不适合使用
- 对象结构频繁变化
- 包含大量不可变/不可复制资源
- 业务复杂,维护成本高
12. 原型模式在实际项目中的应用
- Spring 中的
scope="prototype" - 游戏开发中的角色/子弹复制
- 文档、配置模板
- UI 组件快速生成
当 new 一个对象太慢时,就考虑原型模式。
13. 原型模式的一个重要提醒
原型模式不是为了"少写代码",而是为了"少做重复初始化"。
如果对象创建本身就很轻量,没必要使用原型模式。