【设计模式】原型模式(Prototype Pattern)详解

文章目录

    • [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() 方法

使用方法:

  1. super:调用父类(Object 类)的 clone() 方法
  2. clone():Object 类中定义的本地(native)方法
  3. 整体意思是:"调用 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 深拷贝的常见方式

  1. 手动 clone(最安全)
  2. 序列化 / 反序列化
  3. JSON 转换(不推荐用于高性能场景)

9. 原型模式的优点

  1. 提高性能
  2. 避免复杂初始化
  3. 动态创建对象
  4. 简化工厂类结构

10. 原型模式的缺点

  1. clone 实现复杂
  2. 深拷贝容易出错
  3. 破坏封装性
  4. 对象结构复杂时维护成本高

11. 适用场景

适合使用

  • 创建对象成本高
  • 对象差异小
  • 需要大量相似对象
  • 原型实例较稳定

不适合使用

  • 对象结构频繁变化
  • 包含大量不可变/不可复制资源
  • 业务复杂,维护成本高

12. 原型模式在实际项目中的应用

  • Spring 中的 scope="prototype"
  • 游戏开发中的角色/子弹复制
  • 文档、配置模板
  • UI 组件快速生成

当 new 一个对象太慢时,就考虑原型模式。


13. 原型模式的一个重要提醒

原型模式不是为了"少写代码",而是为了"少做重复初始化"。

如果对象创建本身就很轻量,没必要使用原型模式


参考

原型模式 | 菜鸟教程

原型设计模式

原型模式-百度百科

《图解设计模式》

原型 - Java教程 - 廖雪峰的官方网站

相关推荐
杨充1 天前
10.可测试性实战设计
设计模式·开源·代码规范
杨充1 天前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯2 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式