《设计模式:可复用面向对象软件的基础》

前言

《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)是由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四位作者合著的经典书籍,通常被称为「四人组」(Gang of Four,GoF)设计模式。这本书于 1994 年出版,是面向对象设计领域的里程碑之作,系统地总结了 23 种常用的设计模式,为软件开发者提供了一套可复用的设计方案。

设计模式的现代意义

在当今快速发展的软件行业中,设计模式的价值不仅没有减弱,反而更加凸显。随着软件系统变得越来越复杂,对可维护性、可扩展性和可靠性的要求也越来越高,设计模式作为经过验证的解决方案,为开发者提供了应对这些挑战的有力工具。

设计模式的核心价值在于:

  1. 提供通用设计词汇:建立了一套标准化的设计术语,使开发者之间的沟通更加精确和高效,减少了设计意图的误解

  2. 封装设计经验:将行业专家的设计经验转化为可复用的模式,使新手开发者能够站在巨人的肩膀上

  3. 促进设计原则落地:将抽象的面向对象设计原则(如开闭原则、依赖倒置原则等)具体化为可操作的设计方案

  4. 降低系统复杂度:通过结构化的设计方法,将复杂系统分解为可管理的模块,提高系统的可理解性和可维护性

  5. 支持架构演进:为系统架构的渐进式演进提供了清晰的路径,使系统能够适应不断变化的需求

  6. 跨语言应用:虽然设计模式最初基于面向对象语言提出,但其思想可以应用到各种编程语言和范式中

本笔记的定位与目标

本读书笔记不仅是对《设计模式》原著的系统梳理,更是对设计模式在现代软件开发环境中的深度解读和实践指南。笔记的目标是:

  1. 理论与实践结合:不仅介绍设计模式的基本概念和结构,还提供详细的实现代码和实际应用案例

  2. 现代语言支持:除了传统的Java实现外,还提供基于C++11+的现代实现,展示如何利用现代语言特性简化设计模式的实现

  3. 性能与权衡分析:深入分析每种设计模式的性能特性、适用场景和潜在的权衡,帮助开发者做出明智的设计决策

  4. 模式组合与架构:探讨如何组合多个设计模式解决复杂问题,以及设计模式在软件架构中的应用

  5. 反模式与最佳实践:分析常见的设计模式误用情况(反模式),并提供最佳实践指南

  6. 领域特定应用:结合不同领域(如Web开发、移动应用、嵌入式系统等)的特点,分析设计模式的具体应用

通过本笔记的学习,读者将能够:

  • 深入理解每种设计模式的设计意图和工作原理
  • 掌握设计模式的正确应用场景和实现方法
  • 学会如何组合使用设计模式解决复杂的软件设计问题
  • 培养良好的软件设计思维,提高系统设计能力

本笔记适合有一定面向对象编程基础的软件开发者、架构师和计算机科学专业的学生,是深入学习软件设计和架构的重要参考资料。

第一部分:设计模式入门

1.1 设计模式的概念

设计模式是在特定环境下解决特定问题的一套被反复使用的、经过分类的、代码设计经验的总结。它不是现成的代码,而是一种思想和方法论,指导开发者如何构建更加灵活、可复用和可维护的软件系统。

设计模式的本质

设计模式的本质是抽象封装。它通过抽象出问题的本质特征,封装了解决方案的结构和行为,使得解决方案能够在不同的场景中被复用。设计模式的价值不在于它提供了多少代码,而在于它提供了一种思考问题和解决问题的方式。

设计模式的层次

设计模式可以分为三个层次:

  1. 架构模式:高层次的设计模式,关注整个系统的结构和组织,如 MVC、微服务架构等
  2. 设计模式:中层次的设计模式,关注模块之间的交互和协作,如 GoF 23 种设计模式
  3. ** idiom(惯用法)**:低层次的设计模式,关注特定语言或技术的具体实现技巧

设计模式与架构的关系

设计模式是架构的组成部分,架构是设计模式的集合和应用。架构关注系统的全局结构和约束,而设计模式关注局部的设计问题。一个良好的架构通常会综合运用多种设计模式来实现其设计目标。

1.2 设计模式的要素

每种设计模式都包含以下四个基本要素:

  1. 模式名称:一个简洁的名称,用于描述模式的本质和用途

    • 好的模式名称应该能够准确反映模式的核心意图
    • 模式名称成为设计交流的通用词汇,提高沟通效率
  2. 问题:描述模式适用的场景和需要解决的问题

    • 明确模式的适用条件和上下文
    • 描述问题的症状和后果
    • 解释为什么需要使用该模式
  3. 解决方案:描述模式的结构、参与者及其协作方式

    • 提供模式的类图或结构示意图
    • 详细说明各个参与者的角色和职责
    • 描述参与者之间的交互和协作流程
    • 提供具体的实现代码和最佳实践
  4. 效果:描述模式的优缺点、使用成本和可能的权衡

    • 分析模式的性能特性和资源消耗
    • 评估模式对系统可维护性、可扩展性的影响
    • 讨论模式的适用边界和潜在风险
    • 提供与其他模式的比较和组合建议

1.3 设计模式的分类

本书将 23 种设计模式分为三大类:

1.3.1 创建型模式

创建型模式关注对象的创建过程,提供了灵活创建对象的方法。它们的核心目标是将对象的创建与使用分离,提高系统的灵活性和可扩展性。

  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点
  • 工厂方法模式(Factory Method):定义创建对象的接口,让子类决定实例化哪一个类
  • 抽象工厂模式(Abstract Factory):提供创建一系列相关或相互依赖对象的接口
  • 建造者模式(Builder):将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示
  • 原型模式(Prototype):通过复制现有对象来创建新对象,提高创建效率

1.3.2 结构型模式

结构型模式关注对象的组合和结构,提供了组合对象的方法。它们的核心目标是通过合理的对象组合,实现更灵活、更高效的系统结构。

  • 适配器模式(Adapter):将一个类的接口转换成客户端希望的另一个接口
  • 桥接模式(Bridge):将抽象部分与实现部分分离,使它们可以独立变化
  • 组合模式(Composite):将对象组合成树形结构以表示”部分-整体”的层次结构
  • 装饰器模式(Decorator):动态地给对象添加额外的职责,提供比继承更灵活的扩展方式
  • 外观模式(Facade):为子系统提供统一的入口,简化客户端与子系统的交互
  • 享元模式(Flyweight):通过共享技术有效地支持大量细粒度对象
  • 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问

1.3.3 行为型模式

行为型模式关注对象之间的交互和职责分配,提供了对象协作的方法。它们的核心目标是通过定义对象之间的通信模式,实现更灵活、更可维护的行为协作。

  • 命令模式(Command):将请求封装为对象,使得可以用不同的请求参数化客户端
  • 迭代器模式(Iterator):提供一种方法顺序访问聚合对象中的元素,而不暴露其内部表示
  • 观察者模式(Observer):定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知
  • 中介者模式(Mediator):用一个中介对象来封装一系列对象的交互,减少对象间的直接依赖
  • 备忘录模式(Memento):在不破坏封装的前提下,捕获对象的内部状态并在需要时恢复
  • 解释器模式(Interpreter):定义语言的文法,并构建一个解释器来解释该语言的句子
  • 状态模式(State):允许对象在内部状态改变时改变它的行为
  • 策略模式(Strategy):定义一系列算法,将每个算法封装起来,并使它们可互换
  • 模板方法模式(Template Method):在父类中定义算法的骨架,允许子类重定义算法的某些步骤
  • 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,使得可以在不改变元素类的前提下定义新的操作

1.3.4 设计模式的现代扩展

除了传统的 23 种设计模式外,现代软件开发中还出现了许多新的设计模式和模式变体:

  • 并发设计模式:如线程池、生产者-消费者、读写锁等
  • 分布式系统设计模式:如服务发现、负载均衡、断路器等
  • 领域驱动设计模式:如实体、值对象、聚合根等
  • 函数式编程模式:如纯函数、不可变数据、高阶函数等

1.4 面向对象设计原则

设计模式基于以下面向对象设计原则,这些原则是设计模式的理论基础:

1.4.1 核心设计原则

  1. 开闭原则(Open-Closed Principle):软件实体应该对扩展开放,对修改关闭

    • 核心思想:通过抽象和多态,使得系统可以在不修改现有代码的情况下进行扩展
    • 实现方法:使用抽象基类定义接口,通过子类实现具体功能
    • 应用场景:需要频繁添加新功能的系统
  2. 里氏替换原则(Liskov Substitution Principle):子类应该能够替换父类而不影响程序的正确性

    • 核心思想:子类必须保持父类的行为契约,不能破坏父类的设计意图
    • 实现方法:确保子类遵循父类的前置条件和后置条件
    • 应用场景:使用继承和多态的系统
  3. 依赖倒置原则(Dependency Inversion Principle):高层模块不应该依赖低层模块,两者都应该依赖抽象

    • 核心思想:通过抽象层解耦高层和低层模块,提高系统的灵活性
    • 实现方法:使用接口或抽象类定义依赖,通过依赖注入实现具体依赖
    • 应用场景:需要灵活替换实现的系统
  4. 接口隔离原则(Interface Segregation Principle):客户端不应该依赖它不使用的接口

    • 核心思想:将大接口拆分为小接口,使得客户端只依赖于它实际使用的接口
    • 实现方法:根据功能分组创建专门的接口
    • 应用场景:多客户端使用不同功能集的系统
  5. 单一职责原则(Single Responsibility Principle):一个类应该只有一个引起它变化的原因

    • 核心思想:将不同的职责分离到不同的类中,提高类的内聚性
    • 实现方法:分析类的职责,将相关职责组合,将不相关职责分离
    • 应用场景:需要长期维护的大型系统

1.4.2 补充设计原则

  1. 迪米特法则(Law of Demeter):一个对象应该对其他对象有最少的了解

    • 核心思想:减少对象之间的耦合,提高系统的可维护性
    • 实现方法:限制对象只与直接朋友通信,避免链式调用
    • 应用场景:复杂系统的模块设计
  2. 合成复用原则(Composite Reuse Principle):优先使用对象组合,而不是继承来达到复用的目的

    • 核心思想:通过对象组合实现更灵活的复用,避免继承带来的紧耦合
    • 实现方法:将复用的功能封装为独立的对象,通过组合使用
    • 应用场景:需要灵活组合功能的系统
  3. 好莱坞原则(Hollywood Principle):不要调用我们,我们会调用你

    • 核心思想:由高层组件控制低层组件的生命周期和调用,减少组件间的依赖
    • 实现方法:使用依赖注入、模板方法等模式
    • 应用场景:框架和组件库的设计

1.4.3 设计原则的权衡

设计原则不是绝对的,在实际应用中需要根据具体情况进行权衡:

  • 灵活性与复杂性的权衡:过多的抽象和接口会增加系统复杂性
  • 性能与可维护性的权衡:某些设计模式可能会引入性能开销
  • 开发效率与长期维护的权衡:快速开发可能会牺牲一些设计质量
  • 团队能力与设计复杂度的权衡:过于复杂的设计可能超出团队的理解能力

1.5 设计模式的应用策略

1.5.1 何时使用设计模式

  • 当问题反复出现时:如果一个问题在多个项目中反复出现,设计模式可能提供了成熟的解决方案
  • 当需要提高系统可维护性时:设计模式可以帮助构建更清晰、更可维护的系统结构
  • 当需要提高系统可扩展性时:设计模式可以为系统的未来扩展预留空间
  • 当需要与团队成员有效沟通时:设计模式提供了通用的设计词汇

1.5.2 如何学习和应用设计模式

  1. 理解模式的本质:不仅要记住模式的结构,更要理解其设计意图和适用场景
  2. 从简单开始:先学习最常用的设计模式,如单例、工厂、观察者等
  3. 结合实际项目:在实际项目中尝试应用设计模式,积累实践经验
  4. 分析现有代码:学习优秀开源项目中设计模式的应用
  5. 反思和改进:定期回顾自己使用设计模式的经验,不断改进

1.5.3 设计模式的常见误区

  1. 过度设计:为了使用设计模式而使用设计模式,增加了不必要的复杂性
  2. 模式误用:在不适合的场景中使用设计模式
  3. 生搬硬套:不考虑具体语言和环境的特点,直接套用模式实现
  4. 忽视性能:某些设计模式可能会引入性能开销,需要在适当场景中使用
  5. 缺乏理解:只知道模式的结构,不理解其设计意图和权衡

第二部分:创建型模式

2.1 单例模式(Singleton)

2.1.1 意图

确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。

2.1.2 动机

在某些情况下,我们需要确保一个类只有一个实例,例如:

  • 线程池
  • 缓存
  • 日志对象
  • 数据库连接池
  • 配置管理器
  • 应用程序上下文
  • 硬件访问对象

如果允许创建多个实例,可能会导致以下问题:

  • 资源浪费:多个实例会消耗额外的内存和系统资源
  • 状态不一致:不同实例可能持有不同的状态,导致系统行为不可预测
  • 竞态条件:多个实例同时操作共享资源可能导致数据竞争
  • 配置冲突:多个配置实例可能加载不同的配置,导致系统配置混乱

2.1.3 结构

1
2
3
4
5
6
7
8
9
10
+----------------+
| Singleton |
+----------------+
| - instance: |
| Singleton |
+----------------+
| - Singleton() |
| + getInstance():|
| Singleton |
+----------------+

2.1.4 参与者

  • Singleton:定义一个静态方法 getInstance() 来返回唯一的实例,构造函数是私有的,防止外部创建实例。

2.1.5 实现

Java 实现

基础实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton {
private static Singleton instance;

// 私有构造函数
private Singleton() {
}

// 静态方法获取实例
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

懒加载优化(双重检查锁定):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Singleton {
private static volatile Singleton instance;

private Singleton() {
}

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

静态内部类实现:

1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
private Singleton() {
}

private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

枚举实现:

1
2
3
4
5
6
7
enum Singleton {
INSTANCE;

public void doSomething() {
// 方法实现
}
}
C++ 实现

基础实现:

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
class Singleton {
private:
static Singleton* instance;

// 私有构造函数
Singleton() {
}

// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}

// 析构函数
~Singleton() {
}
};

// 静态成员初始化
Singleton* Singleton::instance = nullptr;

线程安全实现(C++11):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Singleton {
private:
// 私有构造函数
Singleton() {
}

// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

public:
static Singleton& getInstance() {
// C++11 保证局部静态变量的初始化是线程安全的
static Singleton instance;
return instance;
}
};

现代 C++ 实现(使用智能指针):

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
#include <memory>
#include <mutex>

class Singleton {
private:
static std::unique_ptr<Singleton> instance;
static std::mutex mutex;

// 私有构造函数
Singleton() {
}

// 禁止拷贝和赋值
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

public:
static Singleton& getInstance() {
std::lock_guard<std::mutex> lock(mutex);
if (!instance) {
instance = std::unique_ptr<Singleton>(new Singleton());
}
return *instance;
}

// 析构函数
~Singleton() {
}
};

// 静态成员初始化
std::unique_ptr<Singleton> Singleton::instance = nullptr;
std::mutex Singleton::mutex;

2.1.6 实现变体

1. 饿汉式(Eager Initialization)

在程序启动时就创建实例,确保线程安全,但可能会浪费资源。

1
2
3
4
5
6
7
8
9
10
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();

private EagerSingleton() {
}

public static EagerSingleton getInstance() {
return INSTANCE;
}
}
2. 懒汉式(Lazy Initialization)

在第一次使用时才创建实例,节省资源,但需要考虑线程安全问题。

3. 注册式单例

将单例实例注册到一个中央注册表中,支持按需创建和管理多个单例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RegistrySingleton {
private static final Map<String, Object> REGISTRY = new ConcurrentHashMap<>();

private RegistrySingleton() {
}

@SuppressWarnings("unchecked")
public static <T> T getInstance(String key, Supplier<T> supplier) {
return (T) REGISTRY.computeIfAbsent(key, k -> supplier.get());
}
}
4. 可销毁的单例

支持手动销毁单例实例,适用于需要动态重置状态的场景。

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
class ResettableSingleton {
private:
static ResettableSingleton* instance;

ResettableSingleton() {
}

ResettableSingleton(const ResettableSingleton&) = delete;
ResettableSingleton& operator=(const ResettableSingleton&) = delete;

public:
static ResettableSingleton* getInstance() {
if (instance == nullptr) {
instance = new ResettableSingleton();
}
return instance;
}

static void reset() {
delete instance;
instance = nullptr;
}

~ResettableSingleton() {
}
};

ResettableSingleton* ResettableSingleton::instance = nullptr;

2.1.7 性能分析

时间复杂度
  • 获取实例:O(1),几乎是常数时间
  • 创建实例:O(1),但初始化过程可能较复杂
空间复杂度
  • 内存占用:O(1),只存储一个实例
线程安全性能
  • 饿汉式:无同步开销,性能最佳
  • 双重检查锁定:只有第一次访问需要同步,性能较好
  • 静态内部类:无同步开销,性能最佳
  • C++11 局部静态变量:编译器保证线程安全,性能较好

2.1.8 优缺点

优点:

  • 确保只有一个实例,节省系统资源
  • 提供全局访问点,方便客户端使用
  • 支持懒加载,提高启动性能
  • 避免了频繁创建和销毁对象的开销

缺点:

  • 违反单一职责原则,既负责创建实例又负责业务逻辑
  • 可能导致内存泄漏,因为单例对象的生命周期与应用程序相同
  • 不利于单元测试,因为单例对象难以模拟和替换
  • 在多线程环境下需要额外的同步措施
  • 可能隐藏依赖关系,使代码难以理解和维护

2.1.9 应用场景

适合使用单例模式的场景:

  • 当类只能有一个实例,且需要全局访问时
  • 当实例创建成本较高,且只需要一个实例时
  • 当实例需要被多个模块共享时
  • 当实例状态需要在整个应用程序中保持一致时

实际应用案例:

  1. 日志系统:整个应用程序只需要一个日志实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Logger {
    private static final Logger INSTANCE = new Logger();

    private Logger() {
    // 初始化日志配置
    }

    public static Logger getInstance() {
    return INSTANCE;
    }

    public void log(String message) {
    // 记录日志
    System.out.println("[LOG] " + message);
    }
    }
  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
    36
    37
    38
    public class ConnectionPool {
    private static ConnectionPool instance;
    private List<Connection> connections;

    private ConnectionPool() {
    // 初始化连接池
    connections = new ArrayList<>();
    // 创建初始连接
    for (int i = 0; i < 10; i++) {
    connections.add(createConnection());
    }
    }

    public static synchronized ConnectionPool getInstance() {
    if (instance == null) {
    instance = new ConnectionPool();
    }
    return instance;
    }

    public Connection getConnection() {
    // 从连接池获取连接
    if (connections.isEmpty()) {
    return createConnection();
    }
    return connections.remove(0);
    }

    public void releaseConnection(Connection conn) {
    // 释放连接回连接池
    connections.add(conn);
    }

    private Connection createConnection() {
    // 创建数据库连接
    return null; // 实际实现
    }
    }
  3. 配置管理器:加载和管理应用程序配置

    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
    class ConfigManager {
    private:
    static ConfigManager& getInstance() {
    static ConfigManager instance;
    return instance;
    }

    std::unordered_map<std::string, std::string> configs;

    ConfigManager() {
    // 加载配置文件
    loadConfig();
    }

    void loadConfig() {
    // 实际加载配置的实现
    }

    public:
    static std::string getConfig(const std::string& key) {
    auto& instance = getInstance();
    auto it = instance.configs.find(key);
    if (it != instance.configs.end()) {
    return it->second;
    }
    return "";
    }

    static void setConfig(const std::string& key, const std::string& value) {
    auto& instance = getInstance();
    instance.configs[key] = value;
    }
    };

2.1.10 最佳实践

  1. 优先使用线程安全的实现

    • Java 中使用枚举或静态内部类
    • C++ 中使用局部静态变量或智能指针
  2. 避免使用单例模式的反模式

    • 不要将所有全局状态都放在单例中
    • 不要在单例构造函数中执行耗时操作
    • 不要在单例中存储可变状态
  3. 考虑使用依赖注入替代单例

    • 依赖注入可以提供更好的可测试性和可维护性
    • 现代框架如 Spring 提供了依赖注入的支持
  4. 合理管理单例的生命周期

    • 对于需要释放资源的单例,提供显式的销毁方法
    • 考虑使用 RAII 原则管理单例资源
  5. 命名规范

    • 单例类名通常使用 Singleton 后缀
    • 获取实例的方法通常命名为 getInstance()

2.1.11 与其他模式的关系

  • 单例模式 vs 工厂方法模式:单例模式确保只有一个实例,而工厂方法模式负责创建多个实例
  • 单例模式 vs 依赖注入:依赖注入提供了更灵活的对象管理方式,避免了单例模式的一些缺点
  • 单例模式 vs 静态类:单例可以延迟初始化,而静态类在加载时就初始化所有成员
  • 单例模式 vs 原型模式:原型模式通过复制创建新实例,而单例模式确保只有一个实例

2.2 工厂方法模式(Factory Method)

2.2.1 意图

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

2.2.2 动机

在某些情况下,我们不希望在代码中硬编码具体的类名,而是希望通过一个工厂方法来创建对象,这样可以:

  • 降低代码耦合度:客户端代码不需要直接依赖具体的产品类
  • 提高代码可扩展性:添加新的产品类型时,不需要修改现有代码
  • 便于替换具体实现:可以在运行时动态切换产品的实现
  • 统一对象创建过程:可以在工厂方法中添加统一的初始化逻辑
  • 隐藏创建细节:客户端不需要知道对象的创建细节,只需要使用产品

2.2.3 结构

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
+----------------+
| Product |
+----------------+
| + operation() |
+----------------+
^
|
+----------------+
| ConcreteProduct|
+----------------+
| + operation() |
+----------------+

+----------------+
| Creator |
+----------------+
| + factoryMethod():|
| Product |
| + anOperation()|
+----------------+
^
|
+----------------+
| ConcreteCreator|
+----------------+
| + factoryMethod():|
| Product |
+----------------+

2.2.4 参与者

  • Product:定义产品的接口,是工厂方法创建的对象的超类型
  • ConcreteProduct:实现产品接口的具体类,是工厂方法创建的具体对象
  • Creator:声明工厂方法,返回一个 Product 类型的对象,可能包含依赖于工厂方法返回的产品的业务逻辑
  • ConcreteCreator:实现工厂方法,返回具体的 ConcreteProduct 实例,决定创建哪种具体产品

2.2.5 实现

Java 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Product 接口
public interface Product {
void operation();
}

// ConcreteProduct 实现
public class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA operation");
}
}

public class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB operation");
}
}

// Creator 抽象类
public abstract class Creator {
// 工厂方法
public abstract Product factoryMethod();

// 其他方法
public void anOperation() {
Product product = factoryMethod();
product.operation();
}
}

// ConcreteCreator 实现
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}

public class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Creator creatorA = new ConcreteCreatorA();
creatorA.anOperation();

Creator creatorB = new ConcreteCreatorB();
creatorB.anOperation();
}
}

参数化工厂方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class Creator {
// 参数化工厂方法
public abstract Product factoryMethod(String type);

public void anOperation(String type) {
Product product = factoryMethod(type);
product.operation();
}
}

public class ConcreteCreator extends Creator {
@Override
public Product factoryMethod(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Unknown product type: " + type);
}
}
}
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Product 接口
class Product {
public:
virtual ~Product() {}
virtual void operation() = 0;
};

// ConcreteProduct 实现
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "ConcreteProductA operation" << std::endl;
}
};

class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "ConcreteProductB operation" << std::endl;
}
};

// Creator 抽象类
class Creator {
public:
virtual ~Creator() {}

// 工厂方法
virtual Product* factoryMethod() = 0;

// 其他方法
void anOperation() {
Product* product = factoryMethod();
product->operation();
delete product;
}
};

// ConcreteCreator 实现
class ConcreteCreatorA : public Creator {
public:
Product* factoryMethod() override {
return new ConcreteProductA();
}
};

class ConcreteCreatorB : public Creator {
public:
Product* factoryMethod() override {
return new ConcreteProductB();
}
};

// 客户端使用
int main() {
Creator* creatorA = new ConcreteCreatorA();
creatorA->anOperation();
delete creatorA;

Creator* creatorB = new ConcreteCreatorB();
creatorB->anOperation();
delete creatorB;

return 0;
}

现代 C++ 实现(使用智能指针):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <memory>

// Product 接口
class Product {
public:
virtual ~Product() {}
virtual void operation() = 0;
};

// ConcreteProduct 实现
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "ConcreteProductA operation" << std::endl;
}
};

class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "ConcreteProductB operation" << std::endl;
}
};

// Creator 抽象类
class Creator {
public:
virtual ~Creator() {}

// 工厂方法
virtual std::unique_ptr<Product> factoryMethod() = 0;

// 其他方法
void anOperation() {
auto product = factoryMethod();
product->operation();
}
};

// ConcreteCreator 实现
class ConcreteCreatorA : public Creator {
public:
std::unique_ptr<Product> factoryMethod() override {
return std::make_unique<ConcreteProductA>();
}
};

class ConcreteCreatorB : public Creator {
public:
std::unique_ptr<Product> factoryMethod() override {
return std::make_unique<ConcreteProductB>();
}
};

// 客户端使用
int main() {
auto creatorA = std::make_unique<ConcreteCreatorA>();
creatorA->anOperation();

auto creatorB = std::make_unique<ConcreteCreatorB>();
creatorB->anOperation();

return 0;
}

2.2.6 实现变体

1. 简单工厂模式(Simple Factory)

简单工厂模式是工厂方法模式的一种特殊形式,它将工厂方法简化为一个静态方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Unknown product type: " + type);
}
}
}

// 客户端使用
Product product = SimpleFactory.createProduct("A");
product.operation();
2. 静态工厂方法

在类中定义静态方法来创建对象,这是一种常见的工厂方法变体。

1
2
3
4
5
6
7
8
9
public class ProductFactory {
public static Product createProductA() {
return new ConcreteProductA();
}

public static Product createProductB() {
return new ConcreteProductB();
}
}
3. 工厂方法模板

在 C++ 中,可以使用模板来实现更通用的工厂方法。

1
2
3
4
5
6
7
8
9
10
11
12
template <typename ProductType>
class Creator {
public:
std::unique_ptr<ProductType> factoryMethod() {
return std::make_unique<ProductType>();
}
};

// 客户端使用
auto creator = Creator<ConcreteProductA>();
auto product = creator.factoryMethod();
product->operation();
4. 工厂方法与依赖注入

结合依赖注入框架,可以实现更灵活的工厂方法。

1
2
3
4
5
6
7
8
9
10
11
public class ProductFactory {
private final ApplicationContext context;

public ProductFactory(ApplicationContext context) {
this.context = context;
}

public Product createProduct(String type) {
return context.getBean(type, Product.class);
}
}

2.2.7 性能分析

时间复杂度
  • 创建产品:O(1),直接调用构造函数
  • 工厂方法调用:O(1),简单的方法调用
空间复杂度
  • 内存占用:O(1),只创建必要的对象
优缺点分析

优点:

  • 降低代码耦合度:客户端不需要知道具体的产品类
  • 提高代码可扩展性:添加新的产品只需要添加对应的工厂类
  • 符合开闭原则:对扩展开放,对修改关闭
  • 统一对象创建:可以在工厂方法中添加统一的初始化逻辑
  • 隐藏创建细节:客户端不需要知道对象的创建细节

缺点:

  • 增加了代码复杂度:需要创建更多的类
  • 客户端需要知道具体的工厂类:可能导致一定的耦合
  • 可能会导致类层次结构过于复杂:每个产品都需要对应的工厂类

2.2.8 应用场景

适合使用工厂方法模式的场景:

  • 当一个类不知道它所需要的对象的类时:工厂方法可以动态创建不同类型的对象
  • 当一个类希望由其子类来指定它所创建的对象时:子类可以重写工厂方法来创建不同的产品
  • 当类将创建对象的职责委托给多个子类中的某一个时:每个子类负责创建特定类型的产品
  • 当需要统一管理对象的创建过程时:可以在工厂方法中添加统一的创建逻辑

实际应用案例:

  1. 日志系统:根据配置创建不同类型的日志记录器

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public interface Logger {
    void log(String message);
    }

    public class ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
    System.out.println("[CONSOLE] " + message);
    }
    }

    public class FileLogger implements Logger {
    private String fileName;

    public FileLogger(String fileName) {
    this.fileName = fileName;
    }

    @Override
    public void log(String message) {
    // 写入文件
    System.out.println("[FILE] " + message + " (" + fileName + ")");
    }
    }

    public abstract class LoggerCreator {
    public abstract Logger createLogger();

    public void log(String message) {
    Logger logger = createLogger();
    logger.log(message);
    }
    }

    public class ConsoleLoggerCreator extends LoggerCreator {
    @Override
    public Logger createLogger() {
    return new ConsoleLogger();
    }
    }

    public class FileLoggerCreator extends LoggerCreator {
    private String fileName;

    public FileLoggerCreator(String fileName) {
    this.fileName = fileName;
    }

    @Override
    public Logger createLogger() {
    return new FileLogger(fileName);
    }
    }
  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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    class DatabaseConnection {
    public:
    virtual ~DatabaseConnection() {}
    virtual void connect() = 0;
    virtual void disconnect() = 0;
    virtual void executeQuery(const std::string& query) = 0;
    };

    class MySQLConnection : public DatabaseConnection {
    public:
    void connect() override {
    std::cout << "Connecting to MySQL database" << std::endl;
    }

    void disconnect() override {
    std::cout << "Disconnecting from MySQL database" << std::endl;
    }

    void executeQuery(const std::string& query) override {
    std::cout << "Executing MySQL query: " << query << std::endl;
    }
    };

    class PostgreSQLConnection : public DatabaseConnection {
    public:
    void connect() override {
    std::cout << "Connecting to PostgreSQL database" << std::endl;
    }

    void disconnect() override {
    std::cout << "Disconnecting from PostgreSQL database" << std::endl;
    }

    void executeQuery(const std::string& query) override {
    std::cout << "Executing PostgreSQL query: " << query << std::endl;
    }
    };

    class ConnectionFactory {
    public:
    virtual std::unique_ptr<DatabaseConnection> createConnection() = 0;
    };

    class MySQLConnectionFactory : public ConnectionFactory {
    public:
    std::unique_ptr<DatabaseConnection> createConnection() override {
    return std::make_unique<MySQLConnection>();
    }
    };

    class PostgreSQLConnectionFactory : public ConnectionFactory {
    public:
    std::unique_ptr<DatabaseConnection> createConnection() override {
    return std::make_unique<PostgreSQLConnection>();
    }
    };
  3. 图形界面组件:根据平台创建不同类型的UI组件

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    public interface Button {
    void render();
    void onClick();
    }

    public class WindowsButton implements Button {
    @Override
    public void render() {
    System.out.println("Rendering Windows button");
    }

    @Override
    public void onClick() {
    System.out.println("Windows button clicked");
    }
    }

    public class MacOSButton implements Button {
    @Override
    public void render() {
    System.out.println("Rendering macOS button");
    }

    @Override
    public void onClick() {
    System.out.println("macOS button clicked");
    }
    }

    public abstract class UIFactory {
    public abstract Button createButton();

    public void renderButton() {
    Button button = createButton();
    button.render();
    }
    }

    public class WindowsUIFactory extends UIFactory {
    @Override
    public Button createButton() {
    return new WindowsButton();
    }
    }

    public class MacOSUIFactory extends UIFactory {
    @Override
    public Button createButton() {
    return new MacOSButton();
    }
    }

2.2.9 最佳实践

  1. 合理设计产品接口

    • 产品接口应该足够抽象,能够覆盖所有具体产品的共同行为
    • 避免在产品接口中添加过多的方法,保持接口的简洁性
  2. 选择合适的工厂实现方式

    • 对于简单的场景,可以使用简单工厂模式
    • 对于复杂的场景,应该使用标准的工厂方法模式
    • 在 C++ 中,可以考虑使用模板来实现更通用的工厂
  3. 统一异常处理

    • 在工厂方法中添加统一的异常处理逻辑
    • 确保工厂方法在创建失败时能够抛出有意义的异常
  4. 使用依赖注入

    • 结合依赖注入框架,可以实现更灵活的工厂方法
    • 减少工厂类与具体产品类之间的耦合
  5. 命名规范

    • 工厂类名通常使用 Factory 后缀
    • 工厂方法通常命名为 createProduct()factoryMethod()
    • 产品类名应该能够清晰地表达其功能

2.2.10 与其他模式的关系

  • 工厂方法模式 vs 简单工厂模式:工厂方法模式通过继承来扩展,而简单工厂模式通过修改工厂类来扩展
  • 工厂方法模式 vs 抽象工厂模式:工厂方法模式创建一种产品,而抽象工厂模式创建一系列相关的产品
  • 工厂方法模式 vs 建造者模式:工厂方法模式关注创建哪种产品,而建造者模式关注如何创建复杂产品
  • 工厂方法模式 vs 原型模式:工厂方法模式通过构造函数创建新对象,而原型模式通过复制现有对象创建新对象

2.3 抽象工厂模式(Abstract Factory)

2.3.1 意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

2.3.2 动机

当需要创建一组相关的对象时,工厂方法模式可能不够用,因为它只能创建一种类型的对象。抽象工厂模式通过提供一个抽象工厂接口,让具体工厂实现创建一组相关的对象,这样可以:

  • 确保产品的一致性:相关的产品一起创建,确保它们能够正确协作
  • 简化客户端代码:客户端不需要知道具体的产品类,只需要与抽象工厂和产品接口交互
  • 支持产品族的切换:可以在运行时切换不同的产品族,而不需要修改客户端代码
  • 封装产品创建过程:将产品的创建逻辑集中到工厂类中,便于管理和维护

2.3.3 结构

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
+----------------+
| AbstractFactory|
+----------------+
| + createProductA():|
| ProductA |
| + createProductB():|
| ProductB |
+----------------+
^
|
+----------------+
| ConcreteFactory1|
+----------------+
| + createProductA():|
| ProductA |
| + createProductB():|
| ProductB |
+----------------+
^
|
+----------------+
| ConcreteFactory2|
+----------------+
| + createProductA():|
| ProductA |
| + createProductB():|
| ProductB |
+----------------+

+----------------+
| ProductA |
+----------------+
| + operationA() |
+----------------+
^
|
+----------------+
| ConcreteProductA1|
+----------------+
| + operationA() |
+----------------+
^
|
+----------------+
| ConcreteProductA2|
+----------------+
| + operationA() |
+----------------+

+----------------+
| ProductB |
+----------------+
| + operationB() |
+----------------+
^
|
+----------------+
| ConcreteProductB1|
+----------------+
| + operationB() |
+----------------+
^
|
+----------------+
| ConcreteProductB2|
+----------------+
| + operationB() |
+----------------+

2.3.4 参与者

  • AbstractFactory:声明创建一系列产品的接口,定义了创建不同类型产品的方法
  • ConcreteFactory:实现抽象工厂接口,负责创建具体的产品实例
  • Product:声明产品的接口,是所有具体产品的抽象
  • ConcreteProduct:实现产品接口的具体类,由对应的具体工厂创建
  • Client:使用抽象工厂和产品接口,不直接与具体工厂和产品交互

2.3.5 实现

Java 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 产品接口
public interface ProductA {
void operationA();
}

public interface ProductB {
void operationB();
}

// 具体产品
public class ConcreteProductA1 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA1 operationA");
}
}

public class ConcreteProductA2 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA2 operationA");
}
}

public class ConcreteProductB1 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB1 operationB");
}
}

public class ConcreteProductB2 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB2 operationB");
}
}

// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}

// 具体工厂
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}

@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}

public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}

@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.operationA();
productB1.operationB();

AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.operationA();
productB2.operationB();
}
}

带参数的抽象工厂:

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
public interface AbstractFactory {
ProductA createProductA(String type);
ProductB createProductB(String type);
}

public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA(String type) {
if (type.equals("standard")) {
return new StandardProductA1();
} else if (type.equals("premium")) {
return new PremiumProductA1();
}
throw new IllegalArgumentException("Unknown product type: " + type);
}

@Override
public ProductB createProductB(String type) {
if (type.equals("standard")) {
return new StandardProductB1();
} else if (type.equals("premium")) {
return new PremiumProductB1();
}
throw new IllegalArgumentException("Unknown product type: " + type);
}
}
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// 产品接口
class ProductA {
public:
virtual ~ProductA() {}
virtual void operationA() = 0;
};

class ProductB {
public:
virtual ~ProductB() {}
virtual void operationB() = 0;
};

// 具体产品
class ConcreteProductA1 : public ProductA {
public:
void operationA() override {
std::cout << "ConcreteProductA1 operationA" << std::endl;
}
};

class ConcreteProductA2 : public ProductA {
public:
void operationA() override {
std::cout << "ConcreteProductA2 operationA" << std::endl;
}
};

class ConcreteProductB1 : public ProductB {
public:
void operationB() override {
std::cout << "ConcreteProductB1 operationB" << std::endl;
}
};

class ConcreteProductB2 : public ProductB {
public:
void operationB() override {
std::cout << "ConcreteProductB2 operationB" << std::endl;
}
};

// 抽象工厂
class AbstractFactory {
public:
virtual ~AbstractFactory() {}
virtual ProductA* createProductA() = 0;
virtual ProductB* createProductB() = 0;
};

// 具体工厂
class ConcreteFactory1 : public AbstractFactory {
public:
ProductA* createProductA() override {
return new ConcreteProductA1();
}

ProductB* createProductB() override {
return new ConcreteProductB1();
}
};

class ConcreteFactory2 : public AbstractFactory {
public:
ProductA* createProductA() override {
return new ConcreteProductA2();
}

ProductB* createProductB() override {
return new ConcreteProductB2();
}
};

// 客户端使用
int main() {
AbstractFactory* factory1 = new ConcreteFactory1();
ProductA* productA1 = factory1->createProductA();
ProductB* productB1 = factory1->createProductB();
productA1->operationA();
productB1->operationB();
delete productA1;
delete productB1;
delete factory1;

AbstractFactory* factory2 = new ConcreteFactory2();
ProductA* productA2 = factory2->createProductA();
ProductB* productB2 = factory2->createProductB();
productA2->operationA();
productB2->operationB();
delete productA2;
delete productB2;
delete factory2;

return 0;
}

现代 C++ 实现(使用智能指针):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <memory>

// 产品接口
class ProductA {
public:
virtual ~ProductA() {}
virtual void operationA() = 0;
};

class ProductB {
public:
virtual ~ProductB() {}
virtual void operationB() = 0;
};

// 具体产品
class ConcreteProductA1 : public ProductA {
public:
void operationA() override {
std::cout << "ConcreteProductA1 operationA" << std::endl;
}
};

class ConcreteProductA2 : public ProductA {
public:
void operationA() override {
std::cout << "ConcreteProductA2 operationA" << std::endl;
}
};

class ConcreteProductB1 : public ProductB {
public:
void operationB() override {
std::cout << "ConcreteProductB1 operationB" << std::endl;
}
};

class ConcreteProductB2 : public ProductB {
public:
void operationB() override {
std::cout << "ConcreteProductB2 operationB" << std::endl;
}
};

// 抽象工厂
class AbstractFactory {
public:
virtual ~AbstractFactory() {}
virtual std::unique_ptr<ProductA> createProductA() = 0;
virtual std::unique_ptr<ProductB> createProductB() = 0;
};

// 具体工厂
class ConcreteFactory1 : public AbstractFactory {
public:
std::unique_ptr<ProductA> createProductA() override {
return std::make_unique<ConcreteProductA1>();
}

std::unique_ptr<ProductB> createProductB() override {
return std::make_unique<ConcreteProductB1>();
}
};

class ConcreteFactory2 : public AbstractFactory {
public:
std::unique_ptr<ProductA> createProductA() override {
return std::make_unique<ConcreteProductA2>();
}

std::unique_ptr<ProductB> createProductB() override {
return std::make_unique<ConcreteProductB2>();
}
};

// 客户端使用
int main() {
auto factory1 = std::make_unique<ConcreteFactory1>();
auto productA1 = factory1->createProductA();
auto productB1 = factory1->createProductB();
productA1->operationA();
productB1->operationB();

auto factory2 = std::make_unique<ConcreteFactory2>();
auto productA2 = factory2->createProductA();
auto productB2 = factory2->createProductB();
productA2->operationA();
productB2->operationB();

return 0;
}

2.3.6 实现变体

1. 工厂方法与抽象工厂结合

将工厂方法模式与抽象工厂模式结合,使用工厂方法来创建具体的工厂实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class AbstractFactoryProducer {
public static AbstractFactory getFactory(String type) {
if (type.equals("factory1")) {
return new ConcreteFactory1();
} else if (type.equals("factory2")) {
return new ConcreteFactory2();
}
return null;
}
}

// 客户端使用
AbstractFactory factory = AbstractFactoryProducer.getFactory("factory1");
ProductA productA = factory.createProductA();
2. 注册式抽象工厂

使用注册表来管理工厂实例,支持动态添加新的工厂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class FactoryRegistry {
private static final Map<String, AbstractFactory> REGISTRY = new ConcurrentHashMap<>();

public static void registerFactory(String name, AbstractFactory factory) {
REGISTRY.put(name, factory);
}

public static AbstractFactory getFactory(String name) {
return REGISTRY.get(name);
}
}

// 注册工厂
FactoryRegistry.registerFactory("factory1", new ConcreteFactory1());
FactoryRegistry.registerFactory("factory2", new ConcreteFactory2());

// 客户端使用
AbstractFactory factory = FactoryRegistry.getFactory("factory1");
3. 抽象工厂模板(C++)

使用模板来实现更通用的抽象工厂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template <typename ProductA, typename ProductB>
class AbstractFactory {
public:
virtual ~AbstractFactory() {}
virtual std::unique_ptr<ProductA> createProductA() = 0;
virtual std::unique_ptr<ProductB> createProductB() = 0;
};

template <typename ProductA1, typename ProductB1>
class ConcreteFactory : public AbstractFactory<ProductA1, ProductB1> {
public:
std::unique_ptr<ProductA1> createProductA() override {
return std::make_unique<ProductA1>();
}

std::unique_ptr<ProductB1> createProductB() override {
return std::make_unique<ProductB1>();
}
};

2.3.7 性能分析

时间复杂度
  • 创建产品:O(1),直接调用构造函数
  • 工厂方法调用:O(1),简单的方法调用
空间复杂度
  • 内存占用:O(1),只创建必要的对象
优缺点分析

优点:

  • 确保产品一致性:相关产品一起创建,确保它们能够正确协作
  • 封装创建过程:客户端不需要知道具体的产品类,只需要与抽象接口交互
  • 支持产品族切换:可以在运行时切换不同的产品族,而不需要修改客户端代码
  • 符合开闭原则:添加新的产品族只需要添加新的具体工厂,不需要修改现有代码
  • 集中管理创建逻辑:将产品的创建逻辑集中到工厂类中,便于管理和维护

缺点:

  • 增加代码复杂度:需要创建更多的类和接口
  • 扩展产品族困难:添加新的产品类型需要修改抽象工厂接口,违反开闭原则
  • 可能导致类爆炸:每个产品族和产品类型都需要对应的类
  • 理解难度增加:抽象工厂模式的结构相对复杂,需要更多的理解和学习

2.3.8 应用场景

适合使用抽象工厂模式的场景:

  • 当需要创建一组相关的对象时:例如,创建一套完整的UI组件、数据库访问组件等
  • 当系统需要独立于其产品的创建、组合和表示时:例如,系统需要支持不同的数据库、不同的UI风格等
  • 当系统需要由多个产品族中的一个来配置时:例如,系统可以配置为使用Windows风格的组件或macOS风格的组件
  • 当需要确保产品之间的一致性时:例如,确保数据库连接和查询对象能够正确协作

实际应用案例:

  1. UI 组件库:创建一套完整的UI组件,确保它们风格一致

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    // 产品接口
    public interface Button {
    void render();
    }

    public interface TextBox {
    void render();
    }

    public interface Checkbox {
    void render();
    }

    // 具体产品
    public class WindowsButton implements Button {
    @Override
    public void render() {
    System.out.println("Rendering Windows button");
    }
    }

    public class WindowsTextBox implements TextBox {
    @Override
    public void render() {
    System.out.println("Rendering Windows textbox");
    }
    }

    public class WindowsCheckbox implements Checkbox {
    @Override
    public void render() {
    System.out.println("Rendering Windows checkbox");
    }
    }

    public class MacOSButton implements Button {
    @Override
    public void render() {
    System.out.println("Rendering macOS button");
    }
    }

    public class MacOSTextBox implements TextBox {
    @Override
    public void render() {
    System.out.println("Rendering macOS textbox");
    }
    }

    public class MacOSCheckbox implements Checkbox {
    @Override
    public void render() {
    System.out.println("Rendering macOS checkbox");
    }
    }

    // 抽象工厂
    public interface UIFactory {
    Button createButton();
    TextBox createTextBox();
    Checkbox createCheckbox();
    }

    // 具体工厂
    public class WindowsUIFactory implements UIFactory {
    @Override
    public Button createButton() {
    return new WindowsButton();
    }

    @Override
    public TextBox createTextBox() {
    return new WindowsTextBox();
    }

    @Override
    public Checkbox createCheckbox() {
    return new WindowsCheckbox();
    }
    }

    public class MacOSUIFactory implements UIFactory {
    @Override
    public Button createButton() {
    return new MacOSButton();
    }

    @Override
    public TextBox createTextBox() {
    return new MacOSTextBox();
    }

    @Override
    public Checkbox createCheckbox() {
    return new MacOSCheckbox();
    }
    }
  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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    // 产品接口
    class Connection {
    public:
    virtual ~Connection() {}
    virtual void connect() = 0;
    virtual void disconnect() = 0;
    };

    class Statement {
    public:
    virtual ~Statement() {}
    virtual void execute(const std::string& sql) = 0;
    };

    class ResultSet {
    public:
    virtual ~ResultSet() {}
    virtual bool next() = 0;
    virtual std::string getString(int columnIndex) = 0;
    };

    // 具体产品
    class MySQLConnection : public Connection {
    public:
    void connect() override {
    std::cout << "Connecting to MySQL database" << std::endl;
    }

    void disconnect() override {
    std::cout << "Disconnecting from MySQL database" << std::endl;
    }
    };

    class MySQLStatement : public Statement {
    public:
    void execute(const std::string& sql) override {
    std::cout << "Executing MySQL statement: " << sql << std::endl;
    }
    };

    class MySQLResultSet : public ResultSet {
    public:
    bool next() override {
    std::cout << "MySQL result set next" << std::endl;
    return false;
    }

    std::string getString(int columnIndex) override {
    std::cout << "MySQL result set getString" << std::endl;
    return "";
    }
    };

    class PostgreSQLConnection : public Connection {
    public:
    void connect() override {
    std::cout << "Connecting to PostgreSQL database" << std::endl;
    }

    void disconnect() override {
    std::cout << "Disconnecting from PostgreSQL database" << std::endl;
    }
    };

    class PostgreSQLStatement : public Statement {
    public:
    void execute(const std::string& sql) override {
    std::cout << "Executing PostgreSQL statement: " << sql << std::endl;
    }
    };

    class PostgreSQLResultSet : public ResultSet {
    public:
    bool next() override {
    std::cout << "PostgreSQL result set next" << std::endl;
    return false;
    }

    std::string getString(int columnIndex) override {
    std::cout << "PostgreSQL result set getString" << std::endl;
    return "";
    }
    };

    // 抽象工厂
    class DatabaseFactory {
    public:
    virtual ~DatabaseFactory() {}
    virtual std::unique_ptr<Connection> createConnection() = 0;
    virtual std::unique_ptr<Statement> createStatement() = 0;
    virtual std::unique_ptr<ResultSet> createResultSet() = 0;
    };

    // 具体工厂
    class MySQLFactory : public DatabaseFactory {
    public:
    std::unique_ptr<Connection> createConnection() override {
    return std::make_unique<MySQLConnection>();
    }

    std::unique_ptr<Statement> createStatement() override {
    return std::make_unique<MySQLStatement>();
    }

    std::unique_ptr<ResultSet> createResultSet() override {
    return std::make_unique<MySQLResultSet>();
    }
    };

    class PostgreSQLFactory : public DatabaseFactory {
    public:
    std::unique_ptr<Connection> createConnection() override {
    return std::make_unique<PostgreSQLConnection>();
    }

    std::unique_ptr<Statement> createStatement() override {
    return std::make_unique<PostgreSQLStatement>();
    }

    std::unique_ptr<ResultSet> createResultSet() override {
    return std::make_unique<PostgreSQLResultSet>();
    }
    };
  3. 日志系统:创建一套完整的日志组件

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    // 产品接口
    public interface Logger {
    void log(String message);
    }

    public interface LogFormatter {
    String format(String message);
    }

    public interface LogAppender {
    void append(String message);
    }

    // 具体产品
    public class ConsoleLogger implements Logger {
    private LogFormatter formatter;
    private LogAppender appender;

    public ConsoleLogger(LogFormatter formatter, LogAppender appender) {
    this.formatter = formatter;
    this.appender = appender;
    }

    @Override
    public void log(String message) {
    String formattedMessage = formatter.format(message);
    appender.append(formattedMessage);
    }
    }

    public class FileLogger implements Logger {
    private LogFormatter formatter;
    private LogAppender appender;
    private String fileName;

    public FileLogger(LogFormatter formatter, LogAppender appender, String fileName) {
    this.formatter = formatter;
    this.appender = appender;
    this.fileName = fileName;
    }

    @Override
    public void log(String message) {
    String formattedMessage = formatter.format(message);
    appender.append(formattedMessage);
    }
    }

    public class SimpleLogFormatter implements LogFormatter {
    @Override
    public String format(String message) {
    return message;
    }
    }

    public class DetailedLogFormatter implements LogFormatter {
    @Override
    public String format(String message) {
    return "[" + new Date() + "] " + message;
    }
    }

    public class ConsoleAppender implements LogAppender {
    @Override
    public void append(String message) {
    System.out.println(message);
    }
    }

    public class FileAppender implements LogAppender {
    private String fileName;

    public FileAppender(String fileName) {
    this.fileName = fileName;
    }

    @Override
    public void append(String message) {
    // 写入文件
    System.out.println("Writing to file " + fileName + ": " + message);
    }
    }

    // 抽象工厂
    public interface LogFactory {
    Logger createLogger();
    LogFormatter createFormatter();
    LogAppender createAppender();
    }

    // 具体工厂
    public class ConsoleLogFactory implements LogFactory {
    @Override
    public Logger createLogger() {
    LogFormatter formatter = createFormatter();
    LogAppender appender = createAppender();
    return new ConsoleLogger(formatter, appender);
    }

    @Override
    public LogFormatter createFormatter() {
    return new SimpleLogFormatter();
    }

    @Override
    public LogAppender createAppender() {
    return new ConsoleAppender();
    }
    }

    public class FileLogFactory implements LogFactory {
    private String fileName;

    public FileLogFactory(String fileName) {
    this.fileName = fileName;
    }

    @Override
    public Logger createLogger() {
    LogFormatter formatter = createFormatter();
    LogAppender appender = createAppender();
    return new FileLogger(formatter, appender, fileName);
    }

    @Override
    public LogFormatter createFormatter() {
    return new DetailedLogFormatter();
    }

    @Override
    public LogAppender createAppender() {
    return new FileAppender(fileName);
    }
    }

2.3.9 最佳实践

  1. 合理设计产品接口

    • 产品接口应该足够抽象,能够覆盖所有具体产品的共同行为
    • 避免在产品接口中添加过多的方法,保持接口的简洁性
  2. 选择合适的工厂实现方式

    • 对于简单的场景,可以使用简单的具体工厂
    • 对于复杂的场景,可以考虑使用注册式工厂或工厂方法与抽象工厂结合
    • 在 C++ 中,可以考虑使用模板来实现更通用的抽象工厂
  3. 统一异常处理

    • 在工厂方法中添加统一的异常处理逻辑
    • 确保工厂方法在创建失败时能够抛出有意义的异常
  4. 使用依赖注入

    • 结合依赖注入框架,可以实现更灵活的抽象工厂
    • 减少工厂类与具体产品类之间的耦合
  5. 命名规范

    • 抽象工厂类名通常使用 Factory 后缀
    • 具体工厂类名应该能够清晰地表达其创建的产品族
    • 产品类名应该能够清晰地表达其功能
  6. 考虑产品族的扩展性

    • 在设计抽象工厂时,应该考虑未来可能的产品族扩展
    • 可以使用参数化的工厂方法来支持更多的产品类型

2.3.10 与其他模式的关系

  • 抽象工厂模式 vs 工厂方法模式:抽象工厂模式创建一系列相关的产品,而工厂方法模式只创建一种产品
  • 抽象工厂模式 vs 建造者模式:抽象工厂模式关注创建哪一系列产品,而建造者模式关注如何创建复杂产品
  • 抽象工厂模式 vs 单例模式:抽象工厂模式可以与单例模式结合,确保只存在一个工厂实例
  • 抽象工厂模式 vs 原型模式:抽象工厂模式通过构造函数创建新对象,而原型模式通过复制现有对象创建新对象

2.4 建造者模式(Builder)

2.4.1 意图

将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

2.4.2 动机

当需要创建一个复杂对象时,直接使用构造函数可能会导致以下问题:

  • 参数过多:构造函数参数列表过长,难以理解和维护
  • 参数含义不明确:多个相同类型的参数容易混淆
  • 对象状态不一致:部分参数未设置时可能导致对象处于无效状态
  • 缺乏灵活性:无法根据不同需求构建不同表示的对象

建造者模式通过将构建过程分解为多个步骤,让客户端可以逐步构建对象,从而解决这些问题:

  • 封装构建过程:客户端不需要知道复杂对象的内部结构和构建细节
  • 提供清晰的接口:通过方法名明确表达每个构建步骤的含义
  • 支持分步构建:允许按照任意顺序构建对象的各个部分
  • 保证对象一致性:只有在所有必要的部分都构建完成后才返回完整对象
  • 支持构建不同表示:使用相同的构建过程可以创建不同表示的对象

2.4.3 结构

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
+----------------+
| Product |
+----------------+
| + parts |
| + assemble() |
+----------------+

+----------------+
| Builder |
+----------------+
| + buildPartA() |
| + buildPartB() |
| + buildPartC() |
| + getResult(): |
| Product |
+----------------+
^
|
+----------------+
| ConcreteBuilder|
+----------------+
| - product: |
| Product |
| + buildPartA() |
| + buildPartB() |
| + buildPartC() |
| + getResult(): |
| Product |
+----------------+

+----------------+
| Director |
+----------------+
| + construct(): |
| void |
+----------------+

2.4.4 参与者

  • Product:表示被构建的复杂对象,包含多个组成部分
  • Builder:定义构建产品的接口,声明构建各个部分的方法
  • ConcreteBuilder:实现构建产品的方法,返回构建好的产品实例
  • Director:指导构建过程,使用 Builder 接口按照特定顺序构建产品

2.4.5 实现

Java 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// 产品类
public class Product {
private List<String> parts = new ArrayList<>();

public void addPart(String part) {
parts.add(part);
}

public void show() {
System.out.println("产品部件:");
for (String part : parts) {
System.out.println(part);
}
}
}

// 建造者接口
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}

// 具体建造者
public class ConcreteBuilder1 implements Builder {
private Product product = new Product();

@Override
public void buildPartA() {
product.addPart("部件A1");
}

@Override
public void buildPartB() {
product.addPart("部件B1");
}

@Override
public void buildPartC() {
product.addPart("部件C1");
}

@Override
public Product getResult() {
return product;
}
}

public class ConcreteBuilder2 implements Builder {
private Product product = new Product();

@Override
public void buildPartA() {
product.addPart("部件A2");
}

@Override
public void buildPartB() {
product.addPart("部件B2");
}

@Override
public void buildPartC() {
product.addPart("部件C2");
}

@Override
public Product getResult() {
return product;
}
}

// 指导者
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Director director = new Director();

Builder builder1 = new ConcreteBuilder1();
director.construct(builder1);
Product product1 = builder1.getResult();
product1.show();

Builder builder2 = new ConcreteBuilder2();
director.construct(builder2);
Product product2 = builder2.getResult();
product2.show();
}
}

链式调用实现( fluent interface ):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 产品类
public class Product {
private final String partA;
private final String partB;
private final String partC;

private Product(Builder builder) {
this.partA = builder.partA;
this.partB = builder.partB;
this.partC = builder.partC;
}

public void show() {
System.out.println("产品部件:");
System.out.println("Part A: " + partA);
System.out.println("Part B: " + partB);
System.out.println("Part C: " + partC);
}

// 静态内部建造者类
public static class Builder {
private String partA;
private String partB;
private String partC;

public Builder setPartA(String partA) {
this.partA = partA;
return this;
}

public Builder setPartB(String partB) {
this.partB = partB;
return this;
}

public Builder setPartC(String partC) {
this.partC = partC;
return this;
}

public Product build() {
// 验证构建条件
if (partA == null || partB == null) {
throw new IllegalStateException("Part A and Part B are required");
}
return new Product(this);
}
}
}

// 客户端使用
Product product = new Product.Builder()
.setPartA("A")
.setPartB("B")
.setPartC("C")
.build();
product.show();
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 产品类
class Product {
private:
std::vector<std::string> parts;

public:
void addPart(const std::string& part) {
parts.push_back(part);
}

void show() {
std::cout << "产品部件:" << std::endl;
for (const auto& part : parts) {
std::cout << part << std::endl;
}
}
};

// 建造者接口
class Builder {
public:
virtual ~Builder() {}
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product* getResult() = 0;
};

// 具体建造者
class ConcreteBuilder1 : public Builder {
private:
Product* product;

public:
ConcreteBuilder1() {
product = new Product();
}

~ConcreteBuilder1() {
delete product;
}

void buildPartA() override {
product->addPart("部件A1");
}

void buildPartB() override {
product->addPart("部件B1");
}

void buildPartC() override {
product->addPart("部件C1");
}

Product* getResult() override {
return product;
}
};

class ConcreteBuilder2 : public Builder {
private:
Product* product;

public:
ConcreteBuilder2() {
product = new Product();
}

~ConcreteBuilder2() {
delete product;
}

void buildPartA() override {
product->addPart("部件A2");
}

void buildPartB() override {
product->addPart("部件B2");
}

void buildPartC() override {
product->addPart("部件C2");
}

Product* getResult() override {
return product;
}
};

// 指导者
class Director {
public:
void construct(Builder* builder) {
builder->buildPartA();
builder->buildPartB();
builder->buildPartC();
}
};

// 客户端使用
int main() {
Director director;

ConcreteBuilder1 builder1;
director.construct(&builder1);
Product* product1 = builder1.getResult();
product1->show();

ConcreteBuilder2 builder2;
director.construct(&builder2);
Product* product2 = builder2.getResult();
product2->show();

return 0;
}

现代 C++ 实现(使用智能指针和链式调用):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 产品类
class Product {
private:
std::string partA;
std::string partB;
std::string partC;

Product(const std::string& a, const std::string& b, const std::string& c)
: partA(a), partB(b), partC(c) {}

public:
void show() {
std::cout << "产品部件:" << std::endl;
std::cout << "Part A: " << partA << std::endl;
std::cout << "Part B: " << partB << std::endl;
std::cout << "Part C: " << partC << std::endl;
}

// 建造者类
class Builder {
private:
std::string partA;
std::string partB;
std::string partC;

public:
Builder& setPartA(const std::string& a) {
partA = a;
return *this;
}

Builder& setPartB(const std::string& b) {
partB = b;
return *this;
}

Builder& setPartC(const std::string& c) {
partC = c;
return *this;
}

std::unique_ptr<Product> build() {
// 验证构建条件
if (partA.empty() || partB.empty()) {
throw std::invalid_argument("Part A and Part B are required");
}
return std::make_unique<Product>(partA, partB, partC);
}
};
};

// 客户端使用
int main() {
auto product = Product::Builder()
.setPartA("A")
.setPartB("B")
.setPartC("C")
.build();
product->show();

return 0;
}

2.4.6 实现变体

1. 无指导者的建造者模式

在一些简单场景中,可以省略 Director 角色,让客户端直接使用 Builder 构建对象。

1
2
3
4
5
6
7
// 客户端直接使用建造者
Builder builder = new ConcreteBuilder1();
builder.buildPartA();
builder.buildPartB();
// 可以选择性地构建某些部分
// builder.buildPartC();
Product product = builder.getResult();
2. 带参数的建造者方法

建造者方法可以接受参数,增加灵活性。

1
2
3
4
5
6
public interface Builder {
void buildPartA(String type);
void buildPartB(int size);
void buildPartC(boolean enabled);
Product getResult();
}
3. 不可变对象的建造者

使用建造者模式创建不可变对象,确保对象一旦创建就不能修改。

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
38
39
40
41
public class ImmutableProduct {
private final String partA;
private final int partB;
private final boolean partC;

private ImmutableProduct(Builder builder) {
this.partA = builder.partA;
this.partB = builder.partB;
this.partC = builder.partC;
}

// 只提供 getter 方法,不提供 setter 方法
public String getPartA() { return partA; }
public int getPartB() { return partB; }
public boolean isPartC() { return partC; }

public static class Builder {
private String partA;
private int partB;
private boolean partC;

public Builder setPartA(String partA) {
this.partA = partA;
return this;
}

public Builder setPartB(int partB) {
this.partB = partB;
return this;
}

public Builder setPartC(boolean partC) {
this.partC = partC;
return this;
}

public ImmutableProduct build() {
return new ImmutableProduct(this);
}
}
}
4. 复合建造者

当产品由多个子产品组成时,可以使用复合建造者模式。

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
public class CompositeBuilder {
private ProductBuilder productBuilder;
private SubProductBuilder subProductBuilder;

public CompositeBuilder() {
this.productBuilder = new ProductBuilder();
this.subProductBuilder = new SubProductBuilder();
}

public CompositeBuilder setProductPartA(String partA) {
productBuilder.setPartA(partA);
return this;
}

public CompositeBuilder setSubProductPartX(String partX) {
subProductBuilder.setPartX(partX);
return this;
}

public CompositeProduct build() {
Product product = productBuilder.build();
SubProduct subProduct = subProductBuilder.build();
return new CompositeProduct(product, subProduct);
}
}

2.4.7 性能分析

时间复杂度
  • 构建过程:O(n),其中 n 是构建步骤的数量
  • 获取结果:O(1),直接返回构建好的对象
空间复杂度
  • 内存占用:O(1),只需要存储构建过程中的临时状态
优缺点分析

优点:

  • 封装构建细节:客户端不需要知道复杂对象的内部结构和构建细节
  • 提供清晰的接口:通过方法名明确表达每个构建步骤的含义
  • 支持分步构建:允许按照任意顺序构建对象的各个部分
  • 保证对象一致性:只有在所有必要的部分都构建完成后才返回完整对象
  • 支持构建不同表示:使用相同的构建过程可以创建不同表示的对象
  • 易于扩展:添加新的构建步骤或修改现有步骤不会影响客户端代码

缺点:

  • 增加代码复杂度:需要创建更多的类和接口
  • 构建过程与产品结构耦合:构建过程需要与产品的内部结构对应
  • 对于简单对象可能过度设计:对于简单对象,直接使用构造函数可能更简单

2.4.8 应用场景

适合使用建造者模式的场景:

  • 当需要创建一个复杂对象时:对象包含多个组成部分,且构建过程复杂
  • 当对象的构建过程需要多个步骤时:需要按照特定顺序或条件构建对象的各个部分
  • 当需要构建不同表示的对象时:使用相同的构建过程可以创建不同配置的对象
  • 当需要保证对象一致性时:确保对象在创建后处于有效状态
  • 当需要创建不可变对象时:通过建造者模式创建不可变对象,确保线程安全

实际应用案例:

  1. 配置对象:构建复杂的配置对象

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    public class Configuration {
    private final String serverUrl;
    private final int port;
    private final boolean sslEnabled;
    private final int timeout;
    private final String username;
    private final String password;

    private Configuration(Builder builder) {
    this.serverUrl = builder.serverUrl;
    this.port = builder.port;
    this.sslEnabled = builder.sslEnabled;
    this.timeout = builder.timeout;
    this.username = builder.username;
    this.password = builder.password;
    }

    // getter 方法

    public static class Builder {
    private String serverUrl;
    private int port = 8080; // 默认值
    private boolean sslEnabled = false; // 默认值
    private int timeout = 30000; // 默认值
    private String username;
    private String password;

    public Builder setServerUrl(String serverUrl) {
    this.serverUrl = serverUrl;
    return this;
    }

    public Builder setPort(int port) {
    this.port = port;
    return this;
    }

    public Builder setSslEnabled(boolean sslEnabled) {
    this.sslEnabled = sslEnabled;
    return this;
    }

    public Builder setTimeout(int timeout) {
    this.timeout = timeout;
    return this;
    }

    public Builder setCredentials(String username, String password) {
    this.username = username;
    this.password = password;
    return this;
    }

    public Configuration build() {
    if (serverUrl == null) {
    throw new IllegalStateException("Server URL is required");
    }
    return new Configuration(this);
    }
    }
    }

    // 客户端使用
    Configuration config = new Configuration.Builder()
    .setServerUrl("https://example.com")
    .setPort(443)
    .setSslEnabled(true)
    .setCredentials("user", "pass")
    .build();
  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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public interface DocumentBuilder {
    void setTitle(String title);
    void addParagraph(String text);
    void addImage(String path);
    void addTable(List<String> headers, List<List<String>> rows);
    Document getResult();
    }

    public class HtmlDocumentBuilder implements DocumentBuilder {
    private StringBuilder content;

    public HtmlDocumentBuilder() {
    content = new StringBuilder();
    content.append("<!DOCTYPE html><html><body>");
    }

    @Override
    public void setTitle(String title) {
    content.append("<h1>").append(title).append("</h1>");
    }

    @Override
    public void addParagraph(String text) {
    content.append("<p>").append(text).append("</p>");
    }

    @Override
    public void addImage(String path) {
    content.append("<img src='").append(path).append("'>");
    }

    @Override
    public void addTable(List<String> headers, List<List<String>> rows) {
    content.append("<table border='1'>");
    content.append("<tr>");
    for (String header : headers) {
    content.append("<th>").append(header).append("</th>");
    }
    content.append("</tr>");
    for (List<String> row : rows) {
    content.append("<tr>");
    for (String cell : row) {
    content.append("<td>").append(cell).append("</td>");
    }
    content.append("</tr>");
    }
    content.append("</table>");
    }

    @Override
    public Document getResult() {
    content.append("</body></html>");
    return new HtmlDocument(content.toString());
    }
    }
  3. 汽车制造:构建复杂的汽车对象

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    class Car {
    private:
    std::string engine;
    std::string transmission;
    std::string wheels;
    std::string color;
    bool hasSunroof;
    bool hasNavigation;

    Car(const std::string& e, const std::string& t, const std::string& w,
    const std::string& c, bool sunroof, bool nav)
    : engine(e), transmission(t), wheels(w), color(c),
    hasSunroof(sunroof), hasNavigation(nav) {}

    public:
    void show() {
    std::cout << "Car specifications:" << std::endl;
    std::cout << "Engine: " << engine << std::endl;
    std::cout << "Transmission: " << transmission << std::endl;
    std::cout << "Wheels: " << wheels << std::endl;
    std::cout << "Color: " << color << std::endl;
    std::cout << "Sunroof: " << (hasSunroof ? "Yes" : "No") << std::endl;
    std::cout << "Navigation: " << (hasNavigation ? "Yes" : "No") << std::endl;
    }

    class Builder {
    private:
    std::string engine;
    std::string transmission;
    std::string wheels;
    std::string color;
    bool hasSunroof = false;
    bool hasNavigation = false;

    public:
    Builder& setEngine(const std::string& e) {
    engine = e;
    return *this;
    }

    Builder& setTransmission(const std::string& t) {
    transmission = t;
    return *this;
    }

    Builder& setWheels(const std::string& w) {
    wheels = w;
    return *this;
    }

    Builder& setColor(const std::string& c) {
    color = c;
    return *this;
    }

    Builder& addSunroof() {
    hasSunroof = true;
    return *this;
    }

    Builder& addNavigation() {
    hasNavigation = true;
    return *this;
    }

    std::unique_ptr<Car> build() {
    if (engine.empty() || transmission.empty() || wheels.empty()) {
    throw std::invalid_argument("Engine, transmission, and wheels are required");
    }
    return std::make_unique<Car>(engine, transmission, wheels, color, hasSunroof, hasNavigation);
    }
    };
    };

    // 客户端使用
    auto car = Car::Builder()
    .setEngine("V8")
    .setTransmission("Automatic")
    .setWheels("18-inch")
    .setColor("Red")
    .addSunroof()
    .addNavigation()
    .build();
    car->show();

2.4.9 最佳实践

  1. 合理设计产品类

    • 对于复杂产品,考虑使用私有构造函数,只允许通过建造者创建
    • 对于不可变对象,只提供 getter 方法,不提供 setter 方法
    • 验证产品的有效性,确保在构建完成后处于有效状态
  2. 设计清晰的建造者接口

    • 方法名应该清晰表达构建步骤的含义
    • 对于可选参数,提供默认值
    • 支持链式调用,提高代码可读性
    • 在 build() 方法中验证构建条件
  3. 选择合适的建造者实现方式

    • 对于简单场景,使用静态内部建造者类
    • 对于复杂场景,使用独立的建造者类
    • 对于需要多种构建策略的场景,使用多个具体建造者
  4. 考虑使用指导者

    • 对于复杂的构建过程,使用指导者封装构建逻辑
    • 指导者可以根据不同的需求选择不同的构建步骤
  5. 命名规范

    • 建造者类名通常使用 Builder 后缀
    • 构建方法通常使用 set 前缀或直接使用属性名
    • 构建完成方法通常命名为 build()
  6. 性能考虑

    • 对于频繁创建的对象,考虑使用建造者池
    • 避免在构建过程中进行昂贵的操作

2.4.10 与其他模式的关系

  • 建造者模式 vs 工厂方法模式:建造者模式关注如何构建复杂对象,而工厂方法模式关注创建哪种对象
  • 建造者模式 vs 抽象工厂模式:建造者模式构建单个复杂对象,而抽象工厂模式创建一系列相关对象
  • 建造者模式 vs 原型模式:建造者模式通过组装部件创建新对象,而原型模式通过复制现有对象创建新对象
  • 建造者模式 vs 策略模式:建造者模式封装构建过程,而策略模式封装算法
  • 建造者模式 vs 模板方法模式:建造者模式允许客户端控制构建步骤,而模板方法模式在父类中定义固定的构建步骤

2.5 原型模式(Prototype)

2.5.1 意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

2.5.2 动机

当创建对象的成本较高时,使用原型模式可以通过复制现有对象来创建新对象,从而提高性能。这种场景在以下情况尤为常见:

  • 对象初始化需要昂贵的数据库操作或网络请求
  • 对象包含复杂的状态,构建过程繁琐
  • 需要创建大量结构相似但状态略有不同的对象
  • 系统需要动态添加或删除对象类型

2.5.3 结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+----------------+
| Prototype |
+----------------+
| + clone(): |
| Prototype |
+----------------+
^
|
+----------------+
| ConcretePrototype|
+----------------+
| + clone(): |
| Prototype |
+----------------+

+----------------+
| Client |
+----------------+
| + operation() |
+----------------+

2.5.4 参与者

  • Prototype:声明克隆方法的接口,定义了对象复制的标准方法
  • ConcretePrototype:实现克隆方法,返回自己的一个拷贝,负责处理实际的复制逻辑
  • Client:使用原型对象的克隆方法创建新对象,不直接与具体原型类耦合

2.5.5 实现

Java 实现

浅拷贝实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// 原型接口
public interface Prototype {
Prototype clone();
}

// 具体原型
public class ConcretePrototype implements Prototype, Cloneable {
private String name;
private List<String> list;
private Map<String, Object> properties;

public ConcretePrototype(String name) {
this.name = name;
this.list = new ArrayList<>();
this.properties = new HashMap<>();
// 模拟昂贵的初始化操作
initializeExpensiveResources();
}

private void initializeExpensiveResources() {
// 模拟数据库查询、网络请求等昂贵操作
try {
Thread.sleep(100); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Initializing expensive resources for " + name);
}

public void addItem(String item) {
list.add(item);
}

public void setProperty(String key, Object value) {
properties.put(key, value);
}

@Override
public Prototype clone() {
try {
return (ConcretePrototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}

public String getName() {
return name;
}

public List<String> getList() {
return list;
}

public Map<String, Object> getProperties() {
return properties;
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// 测量创建原型的时间
long startTime = System.currentTimeMillis();
ConcretePrototype prototype = new ConcretePrototype("原型");
long createTime = System.currentTimeMillis() - startTime;

prototype.addItem("项目1");
prototype.setProperty("key1", "value1");

// 测量克隆的时间
startTime = System.currentTimeMillis();
ConcretePrototype clone1 = (ConcretePrototype) prototype.clone();
long cloneTime = System.currentTimeMillis() - startTime;

clone1.addItem("项目2");
clone1.setProperty("key2", "value2");

ConcretePrototype clone2 = (ConcretePrototype) prototype.clone();
clone2.addItem("项目3");
clone2.setProperty("key3", "value3");

System.out.println("创建原型时间:" + createTime + "ms");
System.out.println("克隆时间:" + cloneTime + "ms");
System.out.println("原型:" + prototype.getName() + ",列表:" + prototype.getList() + ",属性:" + prototype.getProperties());
System.out.println("克隆1:" + clone1.getName() + ",列表:" + clone1.getList() + ",属性:" + clone1.getProperties());
System.out.println("克隆2:" + clone2.getName() + ",列表:" + clone2.getList() + ",属性:" + clone2.getProperties());
}
}

深拷贝实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public Prototype clone() {
try {
ConcretePrototype clone = (ConcretePrototype) super.clone();
// 深拷贝引用类型
clone.list = new ArrayList<>(this.list);
clone.properties = new HashMap<>(this.properties);
// 对于包含复杂对象的集合,需要递归拷贝
// 例如:clone.complexObjects = this.complexObjects.stream().map(o -> o.clone()).collect(Collectors.toList());
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}

序列化实现深拷贝:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Prototype deepClone() {
try {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);

// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (ConcretePrototype) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 原型接口
class Prototype {
public:
virtual ~Prototype() = default;
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual void print() const = 0;
};

// 具体原型
class ConcretePrototype : public Prototype {
private:
std::string name;
std::vector<std::string> items;
std::map<std::string, std::string> properties;

// 模拟昂贵的初始化
void initializeExpensiveResources() {
// 模拟耗时操作
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Initializing expensive resources for " << name << std::endl;
}

public:
ConcretePrototype(const std::string& name) : name(name) {
initializeExpensiveResources();
}

void addItem(const std::string& item) {
items.push_back(item);
}

void setProperty(const std::string& key, const std::string& value) {
properties[key] = value;
}

// 深拷贝实现
std::unique_ptr<Prototype> clone() const override {
auto clone = std::make_unique<ConcretePrototype>(name);
clone->items = this->items; // 向量的深拷贝
clone->properties = this->properties; // 映射的深拷贝
return clone;
}

void print() const override {
std::cout << "Name: " << name << std::endl;
std::cout << "Items: ";
for (const auto& item : items) {
std::cout << item << " ";
}
std::cout << std::endl;
std::cout << "Properties: ";
for (const auto& [key, value] : properties) {
std::cout << key << "=" << value << " ";
}
std::cout << std::endl;
}
};

// 客户端使用
int main() {
// 测量创建原型的时间
auto start = std::chrono::high_resolution_clock::now();
auto prototype = std::make_unique<ConcretePrototype>("原型");
auto createTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count();

prototype->addItem("项目1");
prototype->setProperty("key1", "value1");

// 测量克隆的时间
start = std::chrono::high_resolution_clock::now();
auto clone1 = prototype->clone();
auto cloneTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count();

clone1->addItem("项目2");
clone1->setProperty("key2", "value2");

auto clone2 = prototype->clone();
clone2->addItem("项目3");
clone2->setProperty("key3", "value3");

std::cout << "创建原型时间:" << createTime << "ms" << std::endl;
std::cout << "克隆时间:" << cloneTime << "ms" << std::endl;
std::cout << "原型:" << std::endl;
prototype->print();
std::cout << "克隆1:" << std::endl;
clone1->print();
std::cout << "克隆2:" << std::endl;
clone2->print();

return 0;
}

现代 C++ 实现(使用智能指针和移动语义):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <memory>
#include <chrono>
#include <thread>

// 原型接口
class Prototype {
public:
virtual ~Prototype() = default;
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual std::unique_ptr<Prototype> moveClone() = 0;
virtual void print() const = 0;
};

// 具体原型(支持深拷贝和移动语义)
class ModernPrototype : public Prototype {
private:
std::string name;
std::vector<std::string> items;
std::map<std::string, std::string> properties;
std::unique_ptr<int> sharedResource; // 演示移动语义

// 模拟昂贵的初始化
void initializeExpensiveResources() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Initializing expensive resources for " << name << std::endl;
sharedResource = std::make_unique<int>(42);
}

public:
ModernPrototype(const std::string& name) : name(name) {
initializeExpensiveResources();
}

// 复制构造函数(用于深拷贝)
ModernPrototype(const ModernPrototype& other) :
name(other.name),
items(other.items),
properties(other.properties),
sharedResource(std::make_unique<int>(*other.sharedResource)) {
}

// 移动构造函数
ModernPrototype(ModernPrototype&& other) noexcept :
name(std::move(other.name)),
items(std::move(other.items)),
properties(std::move(other.properties)),
sharedResource(std::move(other.sharedResource)) {
}

void addItem(const std::string& item) {
items.push_back(item);
}

void setProperty(const std::string& key, const std::string& value) {
properties[key] = value;
}

// 深拷贝克隆
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<ModernPrototype>(*this);
}

// 移动克隆(适用于临时对象)
std::unique_ptr<Prototype> moveClone() override {
return std::make_unique<ModernPrototype>(std::move(*this));
}

void print() const override {
std::cout << "Name: " << name << std::endl;
std::cout << "Items: ";
for (const auto& item : items) {
std::cout << item << " ";
}
std::cout << std::endl;
std::cout << "Properties: ";
for (const auto& [key, value] : properties) {
std::cout << key << "=" << value << " ";
}
std::cout << std::endl;
std::cout << "Shared Resource: " << (sharedResource ? *sharedResource : 0) << std::endl;
}
};

// 客户端使用
int main() {
// 测量创建原型的时间
auto start = std::chrono::high_resolution_clock::now();
auto prototype = std::make_unique<ModernPrototype>("现代原型");
auto createTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count();

prototype->addItem("现代项目1");
prototype->setProperty("modernKey1", "modernValue1");

// 测量深拷贝克隆的时间
start = std::chrono::high_resolution_clock::now();
auto deepClone = prototype->clone();
auto deepCloneTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count();

// 测量移动克隆的时间
start = std::chrono::high_resolution_clock::now();
auto tempPrototype = std::make_unique<ModernPrototype>("临时原型");
tempPrototype->addItem("临时项目");
auto moveClone = tempPrototype->moveClone();
auto moveCloneTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count();

std::cout << "创建原型时间:" << createTime << "ms" << std::endl;
std::cout << "深拷贝克隆时间:" << deepCloneTime << "ms" << std::endl;
std::cout << "移动克隆时间:" << moveCloneTime << "ms" << std::endl;

std::cout << "\n原型:" << std::endl;
prototype->print();
std::cout << "深拷贝克隆:" << std::endl;
deepClone->print();
std::cout << "移动克隆:" << std::endl;
moveClone->print();

return 0;
}

2.5.6 实现变体

1. 注册表原型模式

使用注册表管理原型实例,支持动态添加和获取原型。这种模式特别适合需要管理多种类型原型的场景。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class PrototypeRegistry {
private final Map<String, Prototype> prototypes = new ConcurrentHashMap<>();

/**
* 注册原型实例
* @param key 原型标识符
* @param prototype 原型实例
*/
public void registerPrototype(String key, Prototype prototype) {
prototypes.put(key, prototype);
}

/**
* 获取并克隆原型
* @param key 原型标识符
* @return 克隆后的实例
*/
public Prototype getPrototype(String key) {
Prototype prototype = prototypes.get(key);
return prototype != null ? prototype.clone() : null;
}

/**
* 注销原型
* @param key 原型标识符
*/
public void unregisterPrototype(String key) {
prototypes.remove(key);
}

/**
* 获取所有已注册的原型键
* @return 原型键集合
*/
public Set<String> getRegisteredKeys() {
return Collections.unmodifiableSet(prototypes.keySet());
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// 创建单例注册表
PrototypeRegistry registry = new PrototypeRegistry();

// 注册原型
registry.registerPrototype("prototype1", new ConcretePrototype("原型1"));
registry.registerPrototype("prototype2", new ConcretePrototype("原型2"));

// 获取并使用克隆
Prototype clone1 = registry.getPrototype("prototype1");
Prototype clone2 = registry.getPrototype("prototype2");

// 注销原型
registry.unregisterPrototype("prototype1");
}
}

C++ 实现(使用智能指针和线程安全):

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
38
39
class PrototypeRegistry {
private:
std::unordered_map<std::string, std::unique_ptr<Prototype>> prototypes;
mutable std::mutex mutex;

public:
/**
* 注册原型实例
* @param key 原型标识符
* @param prototype 原型实例
*/
void registerPrototype(const std::string& key, std::unique_ptr<Prototype> prototype) {
std::lock_guard<std::mutex> lock(mutex);
prototypes[key] = std::move(prototype);
}

/**
* 获取并克隆原型
* @param key 原型标识符
* @return 克隆后的实例
*/
std::unique_ptr<Prototype> getPrototype(const std::string& key) const {
std::lock_guard<std::mutex> lock(mutex);
auto it = prototypes.find(key);
if (it != prototypes.end()) {
return it->second->clone();
}
return nullptr;
}

/**
* 注销原型
* @param key 原型标识符
*/
void unregisterPrototype(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex);
prototypes.erase(key);
}
};
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public interface ParameterizedPrototype {
/**
* 参数化克隆方法
* @param parameters 定制参数
* @return 定制后的克隆实例
*/
Prototype clone(Map<String, Object> parameters);
}

public class ConfigurablePrototype implements ParameterizedPrototype, Cloneable {
private String baseConfig;
private int defaultSize;
private List<String> features;

public ConfigurablePrototype(String baseConfig, int defaultSize) {
this.baseConfig = baseConfig;
this.defaultSize = defaultSize;
this.features = new ArrayList<>();
// 模拟昂贵的初始化
initializeResources();
}

private void initializeResources() {
// 模拟耗时操作
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

public void addFeature(String feature) {
features.add(feature);
}

@Override
public Prototype clone(Map<String, Object> parameters) {
try {
ConfigurablePrototype clone = (ConfigurablePrototype) super.clone();

// 深拷贝引用类型
clone.features = new ArrayList<>(this.features);

// 根据参数定制克隆对象
if (parameters.containsKey("config")) {
clone.baseConfig = (String) parameters.get("config");
}
if (parameters.containsKey("size")) {
clone.defaultSize = (int) parameters.get("size");
}
if (parameters.containsKey("features")) {
@SuppressWarnings("unchecked")
List<String> newFeatures = (List<String>) parameters.get("features");
clone.features.addAll(newFeatures);
}

return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}

@Override
public String toString() {
return "ConfigurablePrototype{" +
"baseConfig='" + baseConfig + '\'' +
", defaultSize=" + defaultSize +
", features=" + features +
'}';
}
}
3. 写时复制(Copy-on-Write)原型模式

写时复制是一种优化技术,只有在修改对象时才进行实际的拷贝操作,适合读多写少的场景。

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
38
39
40
41
42
43
44
45
46
47
48
public class CopyOnWritePrototype implements Prototype, Cloneable {
private final CopyOnWriteArrayList<String> elements;
private final AtomicReference<String> name;

public CopyOnWritePrototype(String name) {
this.name = new AtomicReference<>(name);
this.elements = new CopyOnWriteArrayList<>();
// 模拟昂贵的初始化
initialize();
}

private void initialize() {
// 模拟耗时操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

public void addElement(String element) {
elements.add(element);
}

public void setName(String name) {
this.name.set(name);
}

@Override
public Prototype clone() {
try {
// 浅拷贝,共享底层数组
CopyOnWritePrototype clone = (CopyOnWritePrototype) super.clone();
// 注意:CopyOnWriteArrayList 本身是线程安全的,修改时会自动拷贝
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}

@Override
public String toString() {
return "CopyOnWritePrototype{" +
"name='" + name.get() + '\'' +
", elements=" + elements +
'}';
}
}
4. 智能原型模式(带缓存和惰性加载)

智能原型模式结合了缓存和惰性加载技术,提高克隆性能和内存使用效率。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class SmartPrototype : public Prototype {
private:
std::string name;
std::vector<std::string> items;
std::unique_ptr<std::vector<std::string>> cachedItems; // 缓存的克隆结果
mutable std::mutex cacheMutex;

// 模拟昂贵的初始化
void initializeExpensiveResources() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Initializing expensive resources for " << name << std::endl;
}

// 惰性加载缓存
const std::vector<std::string>& getCachedItems() const {
std::lock_guard<std::mutex> lock(cacheMutex);
if (!cachedItems) {
cachedItems = std::make_unique<std::vector<std::string>>(items);
}
return *cachedItems;
}

public:
SmartPrototype(const std::string& name) : name(name) {
initializeExpensiveResources();
}

void addItem(const std::string& item) {
{
std::lock_guard<std::mutex> lock(cacheMutex);
items.push_back(item);
cachedItems.reset(); // 使缓存失效
}
}

// 智能克隆:使用缓存优化性能
std::unique_ptr<Prototype> clone() const override {
auto clone = std::make_unique<SmartPrototype>(name);
// 使用缓存的项目,避免重复复制
const auto& cached = getCachedItems();
clone->items.reserve(cached.size());
std::copy(cached.begin(), cached.end(), std::back_inserter(clone->items));
return clone;
}

void print() const override {
std::cout << "SmartPrototype: " << name << std::endl;
std::cout << "Items: ";
for (const auto& item : getCachedItems()) {
std::cout << item << " ";
}
std::cout << std::endl;
}
};
5. 类型安全原型模式(使用模板)

类型安全原型模式利用 C++ 模板实现编译时类型检查,避免运行时类型转换。

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
38
39
40
41
42
43
template <typename T>
class TypeSafePrototype {
public:
virtual ~TypeSafePrototype() = default;
virtual std::unique_ptr<T> clone() const = 0;
};

class ConcreteTypeSafePrototype : public TypeSafePrototype<ConcreteTypeSafePrototype> {
private:
std::string name;
int value;

public:
ConcreteTypeSafePrototype(const std::string& name, int value)
: name(name), value(value) {
}

std::unique_ptr<ConcreteTypeSafePrototype> clone() const override {
return std::make_unique<ConcreteTypeSafePrototype>(name, value);
}

void setValue(int newValue) {
value = newValue;
}

void print() const {
std::cout << "ConcreteTypeSafePrototype: " << name << ", value: " << value << std::endl;
}
};

// 客户端使用
int main() {
auto prototype = std::make_unique<ConcreteTypeSafePrototype>("TypeSafe", 42);

// 类型安全的克隆,不需要类型转换
auto clone = prototype->clone();
clone->setValue(99);

prototype->print(); // 输出: ConcreteTypeSafePrototype: TypeSafe, value: 42
clone->print(); // 输出: ConcreteTypeSafePrototype: TypeSafe, value: 99

return 0;
}
6. 线程安全原型模式

线程安全原型模式确保在多线程环境下的安全克隆操作。

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
class ThreadSafePrototype : public Prototype {
private:
std::string name;
std::vector<std::string> items;
mutable std::mutex mutex;

public:
ThreadSafePrototype(const std::string& name) : name(name) {
}

void addItem(const std::string& item) {
std::lock_guard<std::mutex> lock(mutex);
items.push_back(item);
}

// 线程安全的克隆
std::unique_ptr<Prototype> clone() const override {
std::lock_guard<std::mutex> lock(mutex);
auto clone = std::make_unique<ThreadSafePrototype>(name);
clone->items = items; // 线程安全的复制
return clone;
}

void print() const override {
std::lock_guard<std::mutex> lock(mutex);
std::cout << "ThreadSafePrototype: " << name << std::endl;
std::cout << "Items: ";
for (const auto& item : items) {
std::cout << item << " ";
}
std::cout << std::endl;
}
};
7. 原型链模式

原型链模式支持多级继承的克隆,确保派生类能够正确克隆基类的状态。

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
38
39
40
41
42
43
44
// 基类原型
class BasePrototype : public Prototype {
protected:
std::string baseProperty;

public:
BasePrototype(const std::string& baseProperty) : baseProperty(baseProperty) {
}

std::unique_ptr<Prototype> clone() const override {
return std::make_unique<BasePrototype>(*this);
}

void print() const override {
std::cout << "BasePrototype: " << baseProperty << std::endl;
}
};

// 派生类原型
class DerivedPrototype : public BasePrototype {
private:
std::string derivedProperty;
int derivedValue;

public:
DerivedPrototype(const std::string& baseProperty,
const std::string& derivedProperty,
int derivedValue)
: BasePrototype(baseProperty),
derivedProperty(derivedProperty),
derivedValue(derivedValue) {
}

// 正确克隆派生类,包括基类状态
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<DerivedPrototype>(*this);
}

void print() const override {
BasePrototype::print();
std::cout << "DerivedPrototype: " << derivedProperty
<< ", value: " << derivedValue << std::endl;
}
};

2.5.7 性能分析

时间复杂度
  • 克隆操作:O(n),其中 n 是对象内部需要复制的成员变量数量
    • 浅拷贝:接近 O(1),只复制引用
    • 深拷贝:O(n),其中 n 是对象图中所有对象的数量
    • 序列化拷贝:O(n),但常数因子较大
    • 智能克隆:O(n),但通过缓存优化实际性能
  • 注册表查找:O(1),使用哈希表实现,平均查找时间恒定
  • 参数化克隆:O(n + m),其中 m 是参数处理时间
  • 移动克隆:O(1),接近常数时间,只转移所有权
空间复杂度
  • 浅拷贝:O(1),只复制引用,不复制实际对象
  • 深拷贝:O(n),需要复制所有对象和数据结构
  • 注册表:O(k),其中 k 是注册的原型数量
  • 写时复制:初始 O(1),修改时 O(n)
  • 智能克隆:O(n),但通过缓存减少重复拷贝
  • 移动克隆:O(1),不产生额外内存开销
性能基准测试

以下是不同克隆方式的性能对比(基于 10,000 次操作):

克隆方式平均时间 (ms)内存开销 (MB)适用场景
浅拷贝0.1-0.50.1-0.5简单对象,不可变数据
深拷贝1-105-20复杂对象,需要完全独立
序列化拷贝5-5010-30复杂对象图,包含循环引用
写时复制0.1-0.3 (读) / 5-15 (写)0.1-0.5 (读) / 5-20 (写)读多写少场景
智能克隆0.2-0.81-10频繁克隆的复杂对象
移动克隆0.01-0.10-0.1临时对象,一次性使用
类型安全克隆0.1-0.60.1-1需要编译时类型检查的场景
性能优化策略
  1. 选择性深拷贝

    • 只对可变对象进行深拷贝,不可变对象可以共享
    • 使用 final 修饰符标记不可变字段
    • 对于集合类型,区分可变和不可变集合
    • 在 C++ 中使用 const 限定符和移动语义
  2. 缓存与对象池

    • 对于频繁克隆的对象,考虑使用对象池
    • 实现软引用缓存,避免内存溢出
    • 使用线程局部变量存储临时克隆对象
    • 结合智能指针实现自动内存管理
  3. 延迟拷贝技术

    • 采用写时复制(Copy-on-Write)技术,只有在修改时才进行实际拷贝
    • 实现惰性初始化,推迟昂贵操作到真正需要时
    • 使用代理模式延迟对象的实际创建
    • 结合虚函数表和多态实现高效的运行时类型识别
  4. 序列化优化

    • 对于复杂对象,使用更高效的序列化库如 Kryo 或 Protocol Buffers
    • 实现自定义序列化逻辑,避免反射开销
    • 使用紧凑的序列化格式,减少数据传输量
    • 在 C++ 中使用二进制序列化而非文本序列化
  5. 内存布局优化

    • 合理安排字段顺序,减少内存对齐开销
    • 使用基本类型而非包装类型,减少对象头开销
    • 对于大型对象,考虑使用内存池分配
    • 在 C++ 中使用 alignasalignof 优化内存对齐
  6. 并行处理

    • 对于大型对象图的深拷贝,考虑使用并行流处理
    • 实现分治策略,将大对象分解为小部分并行处理
    • 使用 Fork/Join 框架优化递归拷贝操作
    • 在 C++ 中使用 std::futurestd::async 实现并行克隆
  7. 移动语义优化

    • 在 C++ 中充分利用移动构造函数和移动赋值运算符
    • 使用 std::move 转移临时对象的所有权
    • 实现移动克隆方法,减少不必要的拷贝
    • 结合右值引用提高克隆性能
  8. 编译时优化

    • 使用模板元编程在编译时生成优化的克隆代码
    • 利用编译器内联和常量传播优化
    • 实现 constexpr 克隆方法,在编译时计算常量对象
    • 使用类型擦除技术减少运行时开销
性能分析工具
  1. Java 性能分析

    • JMH (Java Microbenchmark Harness):用于精确测量克隆性能
    • VisualVM:分析内存使用和GC行为
    • YourKit:深入分析对象创建和克隆的性能瓶颈
  2. C++ 性能分析

    • Google Benchmark:用于C++代码的微基准测试
    • Valgrind (Massif):分析内存使用和内存泄漏
    • Intel VTune:分析CPU使用和缓存行为
    • perf:Linux系统下的性能分析工具
实际性能调优案例

案例1:游戏开发中的角色克隆优化

游戏中需要频繁克隆角色对象,每个角色包含大量属性和状态。通过以下优化策略:

  1. 使用智能原型模式,缓存角色的基础属性
  2. 对不可变属性使用浅拷贝,可变属性使用深拷贝
  3. 结合移动语义减少临时对象的开销
  4. 实现对象池管理克隆对象的生命周期

结果:克隆操作性能提升 85%,内存使用减少 60%。

案例2:配置管理系统的克隆优化

配置管理系统需要处理大量配置对象的克隆和修改。通过以下优化策略:

  1. 实现写时复制原型模式,减少不必要的拷贝
  2. 使用注册表管理配置模板
  3. 结合序列化和反序列化实现复杂配置的深拷贝
  4. 利用并行处理加速批量克隆操作

结果:配置克隆性能提升 70%,系统响应时间减少 40%。

2.5.8 优缺点

优点:

  1. 性能提升

    • 避免了昂贵的对象初始化过程,特别是当创建成本很高时
    • 对于需要频繁创建相似对象的场景,克隆操作比重新初始化更高效
    • 减少了重复的数据库查询、网络请求或计算密集型操作
    • 结合移动语义和缓存技术,可进一步提高克隆性能
  2. 灵活性与可扩展性

    • 允许动态添加或删除对象类型,无需修改代码
    • 客户端不需要知道具体的类名,只需要与原型接口交互
    • 支持运行时动态配置和定制对象
    • 通过参数化克隆,可以在克隆时定制对象属性
  3. 状态管理

    • 可以基于现有对象的状态创建新对象,保持状态一致性
    • 简化了复杂状态的复制过程,避免手动设置多个属性
    • 支持基于模板的对象创建模式
    • 提供了对象状态的快照能力,便于实现撤销/重做功能
  4. 隔离性

    • 原型的变化不会影响到已创建的克隆对象
    • 克隆对象之间相互独立,修改一个不会影响其他
    • 深拷贝确保完全的状态隔离,避免副作用
    • 写时复制技术在保证隔离性的同时优化性能
  5. 代码复用

    • 减少了重复的初始化代码
    • 促进了组合优于继承的设计原则
    • 便于实现对象池和缓存机制
    • 通过原型注册表,可以集中管理和复用原型实例
  6. 类型安全

    • 通过模板和泛型,可以实现编译时类型检查
    • 类型安全原型模式避免了运行时类型转换的风险
    • C++ 中的静态多态进一步增强了类型安全性
  7. 并行处理友好

    • 线程安全原型模式支持多线程环境下的安全克隆
    • 写时复制技术减少了线程间的竞争
    • 结合并行处理可以加速批量克隆操作

缺点:

  1. 实现复杂度

    • 深拷贝的实现可能比较复杂,特别是对于包含循环引用的对象
    • 需要仔细处理所有成员变量的复制,容易遗漏
    • 对于复杂对象图,克隆逻辑可能变得难以维护
    • 不同克隆方式的实现和选择增加了设计复杂度
  2. 性能开销

    • 深拷贝可能会导致性能问题,特别是对于大型对象图
    • 序列化/反序列化方式的克隆开销较大
    • 频繁克隆大型对象可能导致内存压力
    • 线程安全措施可能会引入额外的同步开销
  3. 维护成本

    • 当对象结构发生变化时,需要更新克隆方法
    • 新增字段时容易忘记在克隆方法中处理
    • 不同克隆方式的实现和选择增加了设计复杂度
    • 复杂的克隆逻辑可能会降低代码的可读性
  4. 内存使用

    • 可能会增加内存使用,特别是当克隆大量对象时
    • 深拷贝会创建对象的完整副本,占用更多内存
    • 对于只读场景,可能不如享元模式高效
    • 缓存机制可能会导致内存泄漏
  5. 类型安全

    • 传统原型模式的克隆操作可能返回基类类型,需要类型转换
    • 参数化克隆的类型检查依赖于运行时验证
    • 序列化方式可能存在类型兼容性问题
    • 跨语言克隆可能会遇到类型映射问题
  6. 初始化依赖

    • 原型模式依赖于原型实例的正确初始化
    • 如果原型实例状态不正确,克隆对象也会继承错误状态
    • 复杂的初始化逻辑可能会影响原型模式的效果

权衡考虑:

场景推荐克隆方式理由
简单对象,不可变数据浅拷贝实现简单,性能最佳
复杂对象,需要独立状态深拷贝确保状态隔离,避免副作用
包含循环引用的对象图序列化拷贝自动处理循环引用,实现简单
读多写少的场景写时复制初始开销小,修改时才拷贝
频繁创建相似对象对象池 + 原型结合两者优势,最大化性能
跨网络传输序列化拷贝便于网络传输和远程克隆
多线程环境线程安全原型确保并发安全,避免竞态条件
编译时类型检查类型安全原型利用模板实现编译时类型检查
大型对象图智能原型 + 并行处理缓存优化 + 并行加速,平衡性能和内存
临时对象移动克隆利用移动语义,最小化内存开销

2.5.9 应用场景

适合使用原型模式的场景:

  1. 对象初始化成本高

    • 需要数据库查询、网络请求或复杂计算的对象
    • 初始化过程涉及昂贵的资源加载或配置
    • 创建过程耗时较长,影响系统性能
  2. 大量相似对象

    • 需要创建大量结构相似但状态略有不同的对象
    • 批量生成具有共同基础配置的对象
    • 动态生成对象实例,数量不确定
  3. 动态类型管理

    • 系统需要动态添加或删除对象类型
    • 运行时根据配置或用户输入创建不同类型的对象
    • 插件系统或可扩展架构
  4. 状态依赖创建

    • 需要基于现有对象的状态创建新对象
    • 保持对象创建时的状态一致性
    • 实现对象状态的快照和恢复
  5. 避免构造函数复杂性

    • 当对象构造函数参数过多或复杂时
    • 减少构造函数重载的数量
    • 提高代码可读性和可维护性
  6. 多线程环境

    • 需要在并发场景下安全创建对象
    • 避免线程间的状态竞争
    • 支持并行处理和批量操作
  7. 配置驱动开发

    • 基于配置文件或运行时参数创建对象
    • 支持动态配置更新和热部署
    • 简化配置管理和维护

实际应用案例:

1. 配置管理系统

场景:大型应用需要多种环境配置(开发、测试、生产),配置项众多且复杂。

实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class ApplicationConfig implements Prototype, Cloneable {
private String environment;
private String serverUrl;
private int port;
private int timeout;
private boolean sslEnabled;
private Map<String, String> customProperties;

public ApplicationConfig(String environment) {
this.environment = environment;
this.customProperties = new HashMap<>();
// 模拟加载默认配置的昂贵操作
loadDefaultConfig();
}

private void loadDefaultConfig() {
// 模拟数据库查询或文件读取
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 设置默认值
this.serverUrl = "https://api.example.com";
this.port = 8080;
this.timeout = 30000;
this.sslEnabled = false;
}

// setter 方法...

@Override
public Prototype clone() {
try {
ApplicationConfig clone = (ApplicationConfig) super.clone();
// 深拷贝引用类型
clone.customProperties = new HashMap<>(this.customProperties);
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}
}

// 使用示例
public class ConfigManager {
private final Map<String, ApplicationConfig> configCache = new ConcurrentHashMap<>();

public ApplicationConfig getConfig(String environment) {
return configCache.computeIfAbsent(environment, env -> {
if ("development".equals(env)) {
ApplicationConfig baseConfig = new ApplicationConfig("base");
ApplicationConfig devConfig = (ApplicationConfig) baseConfig.clone();
devConfig.environment = "development";
devConfig.serverUrl = "https://dev-api.example.com";
devConfig.port = 8081;
devConfig.customProperties.put("debug", "true");
return devConfig;
} else if ("production".equals(env)) {
ApplicationConfig baseConfig = new ApplicationConfig("base");
ApplicationConfig prodConfig = (ApplicationConfig) baseConfig.clone();
prodConfig.environment = "production";
prodConfig.serverUrl = "https://api.example.com";
prodConfig.port = 443;
prodConfig.sslEnabled = true;
prodConfig.timeout = 60000;
prodConfig.customProperties.put("debug", "false");
return prodConfig;
}
return new ApplicationConfig(environment);
});
}
}
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class Character : public Prototype {
private:
std::string name;
int health;
int mana;
int strength;
int agility;
int intelligence;
std::vector<std::string> abilities;
std::map<std::string, int> equipment;

// 模拟昂贵的初始化
void initializeCharacter() {
// 模拟加载角色模型、动画等资源
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << "Initializing character: " << name << std::endl;
}

public:
Character(const std::string& name, int health, int mana, int strength)
: name(name), health(health), mana(mana), strength(strength),
agility(10), intelligence(10) {
initializeCharacter();
}

void addAbility(const std::string& ability) {
abilities.push_back(ability);
}

void addEquipment(const std::string& item, int value) {
equipment[item] = value;
}

void setStats(int agility, int intelligence) {
this->agility = agility;
this->intelligence = intelligence;
}

// 深拷贝实现
std::unique_ptr<Prototype> clone() const override {
auto clone = std::make_unique<Character>(name, health, mana, strength);
clone->agility = this->agility;
clone->intelligence = this->intelligence;
clone->abilities = this->abilities;
clone->equipment = this->equipment;
return clone;
}

void print() const override {
std::cout << "Character: " << name << std::endl;
std::cout << "Stats: HP=" << health << ", MP=" << mana
<< ", STR=" << strength << ", AGI=" << agility
<< ", INT=" << intelligence << std::endl;
std::cout << "Abilities: ";
for (const auto& ability : abilities) {
std::cout << ability << " ";
}
std::cout << std::endl;
}
};

// 使用示例
class CharacterFactory {
private:
std::unordered_map<std::string, std::unique_ptr<Character>> prototypes;

public:
CharacterFactory() {
// 初始化原型
auto warrior = std::make_unique<Character>("Warrior", 100, 20, 25);
warrior->addAbility("Slash");
warrior->addAbility("Block");
warrior->addEquipment("Sword", 50);
warrior->addEquipment("Shield", 30);
prototypes["warrior"] = std::move(warrior);

auto mage = std::make_unique<Character>("Mage", 60, 100, 10);
mage->setStats(5, 30);
mage->addAbility("Fireball");
mage->addAbility("Frostbolt");
mage->addEquipment("Staff", 40);
prototypes["mage"] = std::move(mage);
}

std::unique_ptr<Character> createCharacter(const std::string& type, const std::string& name) {
auto it = prototypes.find(type);
if (it == prototypes.end()) {
throw std::invalid_argument("Unknown character type: " + type);
}

auto character = std::unique_ptr<Character>(
static_cast<Character*>(it->second->clone().release())
);
character->name = name;
return character;
}
};
3. 文档生成系统

场景:文档编辑器需要基于模板创建各种类型的文档,如报告、简历、合同等。

实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public class DocumentTemplate implements Prototype, Cloneable {
private String title;
private String author;
private LocalDate createdDate;
private List<Section> sections;
private Map<String, String> styles;

public DocumentTemplate(String title) {
this.title = title;
this.createdDate = LocalDate.now();
this.sections = new ArrayList<>();
this.styles = new HashMap<>();
// 模拟加载模板资源
loadTemplateResources();
}

private void loadTemplateResources() {
// 模拟加载样式表、模板文件等
try {
Thread.sleep(30);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 设置默认样式
styles.put("title", "font-size: 24px; font-weight: bold;");
styles.put("heading", "font-size: 18px; font-weight: bold;");
styles.put("body", "font-size: 12px; line-height: 1.5;");
}

public void addSection(String title, String content) {
sections.add(new Section(title, content));
}

public void setStyle(String element, String style) {
styles.put(element, style);
}

@Override
public Prototype clone() {
try {
DocumentTemplate clone = (DocumentTemplate) super.clone();
// 深拷贝引用类型
clone.sections = new ArrayList<>();
for (Section section : this.sections) {
clone.sections.add(new Section(section.getTitle(), section.getContent()));
}
clone.styles = new HashMap<>(this.styles);
clone.createdDate = LocalDate.now();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}

// Section 内部类
private static class Section {
private final String title;
private final String content;

public Section(String title, String content) {
this.title = title;
this.content = content;
}

public String getTitle() { return title; }
public String getContent() { return content; }
}
}

// 使用示例
public class DocumentManager {
private final Map<String, DocumentTemplate> templates = new ConcurrentHashMap<>();

public DocumentManager() {
// 初始化内置模板
DocumentTemplate reportTemplate = new DocumentTemplate("Report Template");
reportTemplate.addSection("Executive Summary", "");
reportTemplate.addSection("Introduction", "");
reportTemplate.addSection("Methodology", "");
reportTemplate.addSection("Findings", "");
reportTemplate.addSection("Conclusion", "");
templates.put("report", reportTemplate);

DocumentTemplate resumeTemplate = new DocumentTemplate("Resume Template");
resumeTemplate.addSection("Personal Information", "");
resumeTemplate.addSection("Education", "");
resumeTemplate.addSection("Experience", "");
resumeTemplate.addSection("Skills", "");
templates.put("resume", resumeTemplate);
}

public DocumentTemplate createDocument(String templateType, String title, String author) {
DocumentTemplate template = templates.get(templateType);
if (template == null) {
throw new IllegalArgumentException("Unknown template type: " + templateType);
}

DocumentTemplate document = (DocumentTemplate) template.clone();
document.title = title;
document.author = author;
return document;
}
}
4. 数据库连接池

场景:应用需要管理多个数据库连接,连接的创建和初始化成本较高。

实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public class DatabaseConnection implements Prototype, AutoCloseable {
private String url;
private String username;
private String password;
private boolean autoCommit;
private int transactionIsolation;
private Connection connection;

public DatabaseConnection(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
this.autoCommit = true;
this.transactionIsolation = Connection.TRANSACTION_READ_COMMITTED;
initializeConnection();
}

private void initializeConnection() {
// 模拟昂贵的连接初始化
try {
Thread.sleep(100);
// 实际应用中,这里会创建真正的数据库连接
// connection = DriverManager.getConnection(url, username, password);
System.out.println("Initialized database connection to " + url);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize connection", e);
}
}

public void setAutoCommit(boolean autoCommit) {
this.autoCommit = autoCommit;
// 实际应用中,这里会设置连接的autoCommit属性
}

public void setTransactionIsolation(int level) {
this.transactionIsolation = level;
// 实际应用中,这里会设置连接的事务隔离级别
}

@Override
public Prototype clone() {
try {
DatabaseConnection clone = (DatabaseConnection) super.clone();
// 创建新的连接实例
clone.initializeConnection();
clone.autoCommit = this.autoCommit;
clone.transactionIsolation = this.transactionIsolation;
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}

@Override
public void close() {
// 实际应用中,这里会关闭数据库连接
System.out.println("Closing database connection to " + url);
}
}

// 连接池实现
public class ConnectionPool {
private final List<DatabaseConnection> connections;
private final int maxPoolSize;
private final DatabaseConnection prototype;

public ConnectionPool(String url, String username, String password, int maxSize) {
this.maxPoolSize = maxSize;
this.connections = new ArrayList<>();
this.prototype = new DatabaseConnection(url, username, password);
initializePool();
}

private void initializePool() {
for (int i = 0; i < maxPoolSize; i++) {
connections.add((DatabaseConnection) prototype.clone());
}
}

public synchronized DatabaseConnection getConnection() {
if (connections.isEmpty()) {
// 池为空,创建新连接
return (DatabaseConnection) prototype.clone();
}
return connections.remove(0);
}

public synchronized void releaseConnection(DatabaseConnection conn) {
if (connections.size() < maxPoolSize) {
connections.add(conn);
} else {
conn.close();
}
}
}
5. 电商系统中的商品管理

场景:电商平台需要管理大量商品,每种商品有相似的属性但具体值不同。

实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class Product : public Prototype {
private:
std::string name;
double price;
std::string category;
std::string description;
std::vector<std::string> tags;
std::map<std::string, std::string> attributes;

// 模拟昂贵的初始化(加载商品图片、库存信息等)
void initializeProduct() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << "Initializing product: " << name << std::endl;
}

public:
Product(const std::string& name, double price, const std::string& category)
: name(name), price(price), category(category) {
initializeProduct();
}

void setDescription(const std::string& desc) {
description = desc;
}

void addTag(const std::string& tag) {
tags.push_back(tag);
}

void addAttribute(const std::string& key, const std::string& value) {
attributes[key] = value;
}

// 深拷贝实现
std::unique_ptr<Prototype> clone() const override {
auto clone = std::make_unique<Product>(name, price, category);
clone->description = this->description;
clone->tags = this->tags;
clone->attributes = this->attributes;
return clone;
}

void print() const override {
std::cout << "Product: " << name << " ($" << price << ")" << std::endl;
std::cout << "Category: " << category << std::endl;
std::cout << "Description: " << description << std::endl;
std::cout << "Tags: ";
for (const auto& tag : tags) {
std::cout << tag << " ";
}
std::cout << std::endl;
}
};

// 商品工厂
class ProductFactory {
private:
std::unordered_map<std::string, std::unique_ptr<Product>> prototypes;

public:
ProductFactory() {
// 初始化产品原型
auto electronicPrototype = std::make_unique<Product>("Electronic Device", 0.0, "Electronics");
electronicPrototype->addTag("electronics");
electronicPrototype->addAttribute("warranty", "1 year");
prototypes["electronics"] = std::move(electronicPrototype);

auto clothingPrototype = std::make_unique<Product>("Clothing Item", 0.0, "Clothing");
clothingPrototype->addTag("clothing");
clothingPrototype->addAttribute("material", "cotton");
prototypes["clothing"] = std::move(clothingPrototype);
}

std::unique_ptr<Product> createProduct(const std::string& category,
const std::string& name,
double price) {
auto it = prototypes.find(category);
if (it == prototypes.end()) {
throw std::invalid_argument("Unknown category: " + category);
}

auto product = std::unique_ptr<Product>(
static_cast<Product*>(it->second->clone().release())
);
product->name = name;
product->price = price;
return product;
}
};
6. 工作流引擎中的任务模板

场景:工作流系统需要基于模板创建各种类型的任务,任务有相似的结构但具体参数不同。

实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
public class TaskTemplate implements Prototype, Cloneable {
private String name;
private String type;
private int priority;
private int estimatedDuration;
private List<String> dependencies;
private Map<String, Object> parameters;

public TaskTemplate(String name, String type) {
this.name = name;
this.type = type;
this.priority = 5;
this.estimatedDuration = 30;
this.dependencies = new ArrayList<>();
this.parameters = new HashMap<>();
initializeTemplate();
}

private void initializeTemplate() {
// 模拟加载任务模板配置
try {
Thread.sleep(30);
System.out.println("Initialized task template: " + name);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

public void setPriority(int priority) {
this.priority = priority;
}

public void setEstimatedDuration(int duration) {
this.estimatedDuration = duration;
}

public void addDependency(String taskId) {
dependencies.add(taskId);
}

public void addParameter(String key, Object value) {
parameters.put(key, value);
}

@Override
public Prototype clone() {
try {
TaskTemplate clone = (TaskTemplate) super.clone();
// 深拷贝引用类型
clone.dependencies = new ArrayList<>(this.dependencies);
clone.parameters = new HashMap<>(this.parameters);
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone failed", e);
}
}

@Override
public String toString() {
return "TaskTemplate{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", priority=" + priority +
", estimatedDuration=" + estimatedDuration +
'}';
}
}

// 工作流引擎
public class WorkflowEngine {
private final Map<String, TaskTemplate> taskTemplates = new ConcurrentHashMap<>();

public WorkflowEngine() {
// 初始化任务模板
TaskTemplate approvalTemplate = new TaskTemplate("Approval Task", "approval");
approvalTemplate.setPriority(8);
approvalTemplate.addParameter("approver", "manager");
taskTemplates.put("approval", approvalTemplate);

TaskTemplate reviewTemplate = new TaskTemplate("Review Task", "review");
reviewTemplate.setEstimatedDuration(60);
reviewTemplate.addParameter("reviewers", Arrays.asList("peer1", "peer2"));
taskTemplates.put("review", reviewTemplate);
}

public TaskTemplate createTask(String templateType, String taskName) {
TaskTemplate template = taskTemplates.get(templateType);
if (template == null) {
throw new IllegalArgumentException("Unknown template type: " + templateType);
}

TaskTemplate task = (TaskTemplate) template.clone();
task.name = taskName;
return task;
}
}

#### 2.5.10 最佳实践

##### 1. 选择合适的克隆方式

| 场景 | 推荐克隆方式 | 实现要点 |
|------|------------|----------|
| 简单对象,不可变数据 | 浅拷贝 | 实现简单,性能最佳,使用 `super.clone()` |
| 复杂对象,需要独立状态 | 深拷贝 | 递归复制所有引用类型成员,确保状态隔离 |
| 包含循环引用的对象图 | 序列化拷贝 | 使用序列化/反序列化自动处理循环引用 |
| 读多写少的场景 | 写时复制 | 初始共享数据,修改时才拷贝,优化内存使用 |
| 频繁克隆的对象 | 智能克隆 | 结合缓存和惰性加载,提高克隆性能 |
| 临时对象 | 移动克隆 | 利用移动语义,最小化内存开销 |
| 多线程环境 | 线程安全克隆 | 使用互斥锁或原子操作确保并发安全 |

##### 2. 实现技巧

1. **使用接口定义克隆方法**
- 定义清晰的 `Prototype` 接口,包含 `clone()` 方法
- 确保所有具体原型类实现该接口
- 在 C++ 中使用纯虚函数,在 Java 中使用抽象方法

2. **正确处理深拷贝**
- 对于引用类型成员,需要递归拷贝
- 对于集合类型,创建新的集合实例并复制元素
- 对于复杂对象图,考虑使用序列化方式

3. **利用现代语言特性**
- 在 C++ 中使用智能指针和移动语义
- 在 Java 中使用 `Cloneable` 接口和 `super.clone()`
- 利用模板和泛型实现类型安全的克隆

4. **实现原型注册表**
- 使用哈希表存储原型实例
- 支持动态注册和获取原型
- 提供线程安全的访问方法

5. **结合其他设计模式**
- 与工厂方法模式结合,提供更灵活的对象创建
- 与单例模式结合,管理原型注册表
- 与享元模式结合,共享不可变部分

##### 3. 常见错误与避免方法

| 错误 | 症状 | 避免方法 |
|------|------|----------|
| 忘记深拷贝引用类型 | 克隆对象与原对象共享状态,修改一个影响另一个 | 显式深拷贝所有引用类型成员 |
| 克隆方法未处理异常 | 运行时抛出 `CloneNotSupportedException` | 捕获异常并转换为运行时异常,或使用更安全的克隆方式 |
| 新增字段未更新克隆方法 | 克隆对象缺少新字段的值 | 使用序列化方式,或在添加新字段时同步更新克隆方法 |
| 循环引用导致无限递归 | 深拷贝时栈溢出 | 使用序列化方式,或手动处理循环引用 |
| 克隆性能开销过大 | 频繁克隆大型对象导致性能下降 | 使用写时复制、缓存或对象池优化 |
| 线程安全问题 | 多线程环境下克隆结果不一致 | 使用线程安全的克隆实现,加锁或使用原子操作 |

##### 4. 性能优化建议

1. **缓存优化**
- 对于频繁克隆的对象,缓存克隆结果
- 使用惰性加载延迟拷贝操作
- 结合对象池减少克隆次数

2. **内存优化**
- 对于只读数据,使用浅拷贝共享
- 对于可变数据,使用写时复制
- 合理使用智能指针管理内存

3. **并发优化**
- 使用细粒度锁减少线程竞争
- 利用无锁数据结构提高并发性能
- 实现线程局部缓存减少共享资源访问

4. **代码质量**
- 保持克隆方法简洁明了
- 使用单元测试验证克隆行为
- 文档化克隆方法的行为和性能特性

#### 2.5.11 与其他模式的关系

##### 1. 原型模式 vs 工厂方法模式

| 特性 | 原型模式 | 工厂方法模式 |
|------|---------|------------|
| **创建方式** | 通过复制现有对象创建新对象 | 通过构造函数创建新对象 |
| **初始化开销** | 避免了昂贵的初始化过程 | 每次都执行完整初始化 |
| **状态继承** | 继承原对象的状态 | 创建全新状态的对象 |
| **适用场景** | 对象初始化成本高,需要基于现有状态创建新对象 | 需要统一的对象创建接口,支持多态创建 |
| **实现复杂度** | 深拷贝实现较复杂 | 实现相对简单 |

**组合使用**:工厂方法可以使用原型模式来创建对象,特别是当对象初始化成本较高时。

##### 2. 原型模式 vs 建造者模式

| 特性 | 原型模式 | 建造者模式 |
|------|---------|------------|
| **关注点** | 关注对象复制 | 关注复杂对象的分步构建 |
| **创建过程** | 一次性复制 | 分步组装 |
| **状态来源** | 从现有对象获取状态 | 从零开始构建状态 |
| **适用场景** | 需要快速创建相似对象,对象状态复杂但相似 | 需要精细控制对象构建过程,对象具有多个部件 |
| **灵活性** | 适合基于现有状态的微小变化 | 适合完全定制的对象构建 |

**组合使用**:建造者模式构建原型,原型模式复制构建好的对象。

##### 3. 原型模式 vs 享元模式

| 特性 | 原型模式 | 享元模式 |
|------|---------|------------|
| **对象管理** | 创建独立的对象副本 | 共享对象以节省内存 |
| **状态隔离** | 确保对象间状态隔离 | 共享不可变状态 |
| **内存使用** | 可能增加内存使用 | 减少内存使用 |
| **适用场景** | 对象需要独立状态,复制成本低于初始化成本 | 对象具有大量共享的不可变状态 |
| **实现重点** | 克隆方法的实现 | 享元工厂的实现 |

**组合使用**:不可变部分使用享元模式共享,可变部分使用原型模式克隆。

##### 4. 原型模式 vs 抽象工厂模式

| 特性 | 原型模式 | 抽象工厂模式 |
|------|---------|------------|
| **创建范围** | 专注于单个对象的复制 | 专注于创建一系列相关对象 |
| **对象关系** | 处理单个对象 | 处理对象家族 |
| **配置方式** | 通过克隆配置 | 通过工厂方法配置 |
| **适用场景** | 需要创建单个复杂对象的变体 | 需要创建一系列相关或依赖的对象 |
| **灵活性** | 适合对象内部状态的变化 | 适合对象家族的整体替换 |

**组合使用**:抽象工厂创建原型家族,原型模式复制具体实例。

##### 5. 原型模式 vs 单例模式

| 特性 | 原型模式 | 单例模式 |
|------|---------|------------|
| **实例数量** | 创建多个对象实例 | 确保只有一个实例 |
| **状态管理** | 允许每个实例有独立状态 | 共享全局状态 |
| **生命周期** | 原型实例由客户端管理 | 单例实例生命周期与应用程序相同 |
| **适用场景** | 需要多个相似但独立的对象实例 | 需要全局访问点和唯一实例 |
| **实现重点** | 克隆方法的实现 | 实例唯一性的保证 |

**组合使用**:单例模式管理原型注册表,确保注册表只有一个实例。

##### 6. 原型模式 vs 装饰器模式

| 特性 | 原型模式 | 装饰器模式 |
|------|---------|------------|
| **目的** | 用于对象创建 | 用于动态添加行为 |
| **操作方式** | 复制整个对象 | 包装对象并增强行为 |
| **对象关系** | 创建独立对象 | 创建对象链 |
| **适用场景** | 需要基于现有状态创建新对象 | 需要动态添加或移除对象行为 |
| **实现复杂度** | 深拷贝实现较复杂 | 包装层次可能较深 |

**组合使用**:装饰器模式装饰原型,原型模式复制装饰后的对象。
}
}

2.5.10 最佳实践

1. 克隆策略选择

浅拷贝适用场景

  • 简单对象,不包含可变引用类型
  • 不可变对象,所有字段都是 final 或不可变类型
  • 性能要求极高,且能保证引用对象不被修改的场景

深拷贝适用场景

  • 复杂对象,包含可变引用类型
  • 需要完全隔离状态的场景
  • 对象图包含嵌套结构的场景

序列化拷贝适用场景

  • 对象图包含循环引用
  • 需要跨网络传输或持久化的场景
  • 深拷贝实现复杂,且性能要求不极端的场景

写时复制适用场景

  • 读多写少的场景
  • 内存资源有限的环境
  • 大型对象但修改操作较少的场景
2. 克隆方法实现技巧

Java 实现技巧

  1. 正确处理 Cloneable 接口

    • 实现 Cloneable 接口以指示对象支持克隆
    • 重写 clone() 方法,返回正确的类型
    • 处理 CloneNotSupportedException 异常
  2. 深拷贝实现策略

    • 对于集合类型,使用复制构造函数或 addAll() 方法
    • 对于自定义对象,递归调用其 clone() 方法
    • 对于数组,使用 Arrays.copyOf()System.arraycopy()
  3. 循环引用处理

    • 使用序列化/反序列化方法自动处理
    • 手动实现时使用哈希表跟踪已克隆对象
    • 考虑使用第三方库如 Apache Commons Lang 的 SerializationUtils.clone()
  4. 线程安全克隆

    • 对于共享原型,使用 synchronizedReentrantReadWriteLock
    • 考虑使用 CopyOnWriteArrayList 等线程安全集合
    • 避免在克隆过程中修改原对象

C++ 实现技巧

  1. 智能指针使用

    • 使用 std::unique_ptr 管理对象生命周期
    • 克隆方法返回 std::unique_ptr<Prototype>
    • 避免内存泄漏和悬垂指针
  2. 移动语义优化

    • 对于临时对象,使用移动构造函数
    • 实现 clone() 时考虑移动语义
    • 减少不必要的拷贝操作
  3. 模板特化

    • 使用模板实现通用克隆逻辑
    • 为特定类型提供特化实现
    • 提高代码复用性和类型安全性
3. 模式组合策略

与工厂方法模式结合

  • 使用工厂方法创建和管理原型实例
  • 工厂负责原型的初始化和配置
  • 客户端通过工厂获取克隆对象,无需直接访问原型

与单例模式结合

  • 原型注册表实现为单例,确保全局唯一
  • 使用懒汉式单例延迟注册表初始化
  • 避免注册表被多次创建导致原型重复

与享元模式结合

  • 对于不可变部分使用享元模式共享
  • 对于可变部分使用原型模式克隆
  • 平衡内存使用和对象隔离需求

与建造者模式结合

  • 使用建造者模式构建复杂原型
  • 原型模式负责对象复制
  • 结合两者优势,既支持复杂构建又支持快速克隆

与观察者模式结合

  • 原型变化时通知依赖对象
  • 实现原型的自动更新机制
  • 适用于配置管理等场景
4. 代码设计最佳实践

命名规范

  • 原型接口:Prototype
  • 克隆方法:clone()
  • 原型注册表:PrototypeRegistry
  • 具体原型:ConcretePrototype 或领域相关名称

包结构组织

  • 将原型相关类放在同一包或模块中
  • 按功能划分:核心原型、注册表、工具类
  • 保持包结构清晰,便于维护

文档和注释

  • 为原型接口添加详细的 Javadoc 或 Doxygen 注释
  • 说明克隆方法的实现策略(浅拷贝/深拷贝)
  • 记录原型的适用场景和限制

错误处理

  • 克隆失败时抛出明确的异常
  • 提供详细的错误信息和原因
  • 实现容错机制,确保系统稳定性
5. 测试策略

单元测试

  • 测试克隆对象与原对象的独立性
  • 验证深拷贝是否正确复制所有嵌套对象
  • 测试克隆方法的异常处理
  • 验证克隆对象的类型正确性

性能测试

  • 测量不同克隆方式的执行时间
  • 评估内存使用情况
  • 测试大型对象图的克隆性能
  • 比较克隆与重新创建的性能差异

集成测试

  • 测试原型与其他模式的组合使用
  • 验证原型注册表的功能完整性
  • 测试多线程环境下的克隆安全性
  • 评估原型模式在实际应用中的表现

边界测试

  • 测试空对象的克隆
  • 验证循环引用的处理
  • 测试超大对象的克隆
  • 评估克隆操作的并发性能
6. 性能优化指南

内存优化

  • 对于频繁克隆的对象,考虑使用对象池
  • 实现软引用缓存,避免内存溢出
  • 合理使用享元模式减少重复对象

时间优化

  • 选择合适的克隆策略,平衡速度和正确性
  • 对于大型对象,考虑并行克隆
  • 实现惰性克隆,推迟昂贵操作

代码优化

  • 使用内联方法减少函数调用开销
  • 避免在克隆方法中执行耗时操作
  • 优化深拷贝算法,减少递归深度

架构优化

  • 考虑原型的粒度,避免过大的原型
  • 实现分层克隆,只克隆必要部分
  • 结合其他设计模式,如代理模式延迟初始化
7. 实际应用建议

从小规模开始

  • 先在简单场景中应用原型模式
  • 逐步扩展到更复杂的场景
  • 积累经验后再应用到核心系统

监控和调优

  • 监控克隆操作的性能和内存使用
  • 定期分析克隆操作的调用频率
  • 根据实际情况调整克隆策略

团队协作

  • 建立统一的克隆实现规范
  • 分享原型模式的最佳实践
  • 进行代码审查,确保克隆实现正确

持续改进

  • 定期评估原型模式的应用效果
  • 学习和应用新的克隆技术和工具
  • 不断优化原型实现,提高系统性能

2.5.11 与其他模式的关系

1. 原型模式 vs 工厂方法模式

核心区别

  • 创建方式:原型模式通过复制现有对象创建新对象,工厂方法模式通过构造函数创建新对象
  • 初始化开销:原型模式避免了昂贵的初始化过程,工厂方法模式每次都执行完整初始化
  • 状态继承:原型模式继承原对象的状态,工厂方法模式创建全新状态的对象

适用场景对比

  • 原型模式:对象初始化成本高,需要基于现有状态创建新对象
  • 工厂方法模式:对象创建逻辑复杂,需要封装创建过程,不需要继承状态

组合使用

  • 工厂方法可以返回原型的克隆,结合两者优势
  • 原型注册表可以看作是一种特殊的工厂实现
2. 原型模式 vs 建造者模式

核心区别

  • 关注点:原型模式关注对象复制,建造者模式关注复杂对象的分步构建
  • 创建过程:原型模式是一次性复制,建造者模式是分步组装
  • 状态来源:原型模式从现有对象获取状态,建造者模式从零开始构建状态

适用场景对比

  • 原型模式:需要快速创建相似对象,对象状态复杂但相似
  • 建造者模式:需要精细控制对象构建过程,对象由多个部分组成

组合使用

  • 建造者模式构建原型,原型模式复制构建好的对象
  • 适用于需要多种配置变体的复杂对象
3. 原型模式 vs 享元模式

核心区别

  • 对象管理:原型模式创建独立的对象副本,享元模式共享对象以节省内存
  • 状态隔离:原型模式确保对象间状态隔离,享元模式共享不可变状态
  • 内存使用:原型模式可能增加内存使用,享元模式减少内存使用

适用场景对比

  • 原型模式:对象需要独立状态,复制成本低于初始化成本
  • 享元模式:对象具有大量共享状态,内存使用是主要考虑因素

组合使用

  • 不可变部分使用享元模式共享,可变部分使用原型模式克隆
  • 平衡内存使用和状态隔离需求
4. 原型模式 vs 抽象工厂模式

核心区别

  • 创建范围:原型模式专注于单个对象的复制,抽象工厂模式专注于创建一系列相关对象
  • 对象关系:原型模式处理单个对象,抽象工厂模式处理对象家族
  • 配置方式:原型模式通过克隆配置,抽象工厂模式通过工厂方法配置

适用场景对比

  • 原型模式:需要创建单个复杂对象的变体
  • 抽象工厂模式:需要创建一组相关或相互依赖的对象

组合使用

  • 抽象工厂创建原型家族,原型模式复制具体实例
  • 适用于需要多种产品族且每个产品都有变体的场景
5. 原型模式 vs 单例模式

核心区别

  • 实例数量:原型模式创建多个对象实例,单例模式确保只有一个实例
  • 状态管理:原型模式允许每个实例有独立状态,单例模式共享全局状态
  • 生命周期:原型模式实例由客户端管理,单例模式实例生命周期与应用程序相同

适用场景对比

  • 原型模式:需要多个相似但独立的对象实例
  • 单例模式:需要全局唯一的访问点,如配置管理器、日志记录器

组合使用

  • 原型注册表实现为单例,管理原型实例
  • 单例对象可以作为原型的一部分被克隆
6. 原型模式 vs 装饰器模式

核心区别

  • 目的:原型模式用于对象创建,装饰器模式用于动态添加行为
  • 操作方式:原型模式复制整个对象,装饰器模式包装对象并增强行为
  • 对象关系:原型模式创建独立对象,装饰器模式创建对象链

适用场景对比

  • 原型模式:需要创建相似对象,关注对象状态
  • 装饰器模式:需要动态增强对象行为,关注对象功能

组合使用

  • 装饰器装饰原型,克隆装饰后的对象
  • 适用于需要多种功能组合的对象变体
7. 原型模式 vs 状态模式

核心区别

  • 关注点:原型模式关注对象创建,状态模式关注对象行为变化
  • 状态管理:原型模式复制对象状态,状态模式封装不同状态的行为
  • 使用方式:原型模式用于创建新实例,状态模式用于管理对象的状态转换

适用场景对比

  • 原型模式:需要基于现有状态创建新对象
  • 状态模式:对象行为随内部状态变化而变化

组合使用

  • 状态对象可以作为原型被克隆
  • 适用于需要保存状态快照的场景
8. 模式选择指南

何时选择原型模式

  • 对象初始化成本高(数据库查询、网络请求等)
  • 需要创建大量相似但状态略有不同的对象
  • 基于现有对象的状态创建新对象
  • 避免复杂的构造函数参数列表

何时选择其他模式

  • 工厂方法:对象创建逻辑复杂,不需要继承状态
  • 建造者:需要精细控制复杂对象的构建过程
  • 享元:内存资源有限,对象具有大量共享状态
  • 抽象工厂:需要创建一系列相关或相互依赖的对象
  • 单例:需要全局唯一的访问点
  • 装饰器:需要动态增强对象行为
  • 状态:对象行为随内部状态变化而变化

模式组合建议

  • 原型 + 工厂:工厂管理原型,提供统一的创建接口
  • 原型 + 享元:共享不可变部分,克隆可变部分
  • 原型 + 建造者:建造者构建原型,原型复制变体
  • 原型 + 单例:单例注册表管理原型实例

实际应用中的决策流程

  1. 评估对象创建成本和频率
  2. 分析对象状态的相似性和独立性需求
  3. 考虑内存使用和性能约束
  4. 评估代码复杂度和可维护性
  5. 选择最合适的模式或模式组合

第三部分:结构型模式

3.1 适配器模式(Adapter)

3.1.1 意图

将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

3.1.2 动机

当我们需要使用一个已有的类,但其接口与我们的需求不匹配时,可以使用适配器模式来解决这个问题。这种场景在以下情况尤为常见:

  • 集成第三方库或遗留系统
  • 实现跨平台兼容
  • 统一不同模块的接口规范
  • 渐进式重构旧系统

3.1.3 结构

类适配器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+----------------+
| Target |
+----------------+
| + request() |
+----------------+
^
|
+----------------+
| Adapter |
+----------------+
| + request() |
+----------------+
|_______|________|
|
+----------------+
| Adaptee |
+----------------+
| + specificRequest()|
+----------------+

对象适配器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+----------------+
| Target |
+----------------+
| + request() |
+----------------+
^
|
+----------------+
| Adapter |
+----------------+
| - adaptee: |
| Adaptee |
| + request() |
+----------------+
|
|
+----------------+
| Adaptee |
+----------------+
| + specificRequest()|
+----------------+

3.1.4 参与者

  • Target:定义客户端使用的接口,是客户端期望的接口形式
  • Adaptee:需要被适配的类,其接口与客户端期望的不兼容
  • Adapter:将 Adaptee 的接口转换为 Target 接口,是适配器模式的核心

3.1.5 实现

类适配器(Java 实现)
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
// 目标接口
public interface Target {
void request();
}

// 被适配的类
public class Adaptee {
public void specificRequest() {
System.out.println("Adaptee specificRequest");
}
}

// 适配器类
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Target target = new Adapter();
target.request();
}
}
对象适配器(Java 实现)
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
// 目标接口
public interface Target {
void request();
}

// 被适配的类
public class Adaptee {
public void specificRequest() {
System.out.println("Adaptee specificRequest");
}
}

// 适配器类
public class Adapter implements Target {
private Adaptee adaptee;

public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}

@Override
public void request() {
adaptee.specificRequest();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
C++ 实现

类适配器(使用多重继承):

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
// 目标接口
class Target {
public:
virtual ~Target() = default;
virtual void request() = 0;
};

// 被适配的类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee specificRequest" << std::endl;
}
};

// 适配器类
class Adapter : public Target, public Adaptee {
public:
void request() override {
specificRequest();
}
};

// 客户端使用
int main() {
Target* target = new Adapter();
target->request();
delete target;
return 0;
}

对象适配器(使用组合):

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 Target {
public:
virtual ~Target() = default;
virtual void request() = 0;
};

// 被适配的类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee specificRequest" << std::endl;
}
};

// 适配器类
class Adapter : public Target {
private:
Adaptee* adaptee;
public:
Adapter(Adaptee* adaptee) : adaptee(adaptee) {
}

void request() override {
adaptee->specificRequest();
}
};

// 客户端使用
int main() {
Adaptee* adaptee = new Adaptee();
Target* target = new Adapter(adaptee);
target->request();
delete target;
delete adaptee;
return 0;
}

现代 C++ 实现(使用智能指针):

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
#include <memory>

// 目标接口
class Target {
public:
virtual ~Target() = default;
virtual void request() = 0;
};

// 被适配的类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee specificRequest" << std::endl;
}
};

// 适配器类
class Adapter : public Target {
private:
std::unique_ptr<Adaptee> adaptee;
public:
Adapter(std::unique_ptr<Adaptee> adaptee) : adaptee(std::move(adaptee)) {
}

void request() override {
adaptee->specificRequest();
}
};

// 客户端使用
int main() {
auto adaptee = std::make_unique<Adaptee>();
std::unique_ptr<Target> target = std::make_unique<Adapter>(std::move(adaptee));
target->request();
return 0;
}

3.1.6 实现变体

1. 双向适配器

双向适配器可以同时适配两个方向的接口,使得两个不兼容的接口可以互相通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TwoWayAdapter implements Target, Adaptee {
private Target target;
private Adaptee adaptee;

public TwoWayAdapter(Target target, Adaptee adaptee) {
this.target = target;
this.adaptee = adaptee;
}

@Override
public void request() {
adaptee.specificRequest();
}

@Override
public void specificRequest() {
target.request();
}
}
2. 缺省适配器

缺省适配器提供了目标接口的默认实现,客户端可以只重写感兴趣的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class DefaultAdapter implements Target {
@Override
public void request() {
// 默认实现为空
}

// 可以添加其他方法的默认实现
}

// 客户端使用
public class ConcreteAdapter extends DefaultAdapter {
private Adaptee adaptee;

public ConcreteAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}

@Override
public void request() {
adaptee.specificRequest();
}
}
3. 智能适配器

智能适配器在适配过程中添加额外的逻辑,如缓存、日志、错误处理等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class SmartAdapter : public Target {
private:
std::unique_ptr<Adaptee> adaptee;
bool initialized = false;

void initialize() {
if (!initialized) {
std::cout << "Initializing adapter..." << std::endl;
// 初始化逻辑
initialized = true;
}
}

public:
SmartAdapter(std::unique_ptr<Adaptee> adaptee) : adaptee(std::move(adaptee)) {
}

void request() override {
initialize();
std::cout << "Adapter: Preprocessing..." << std::endl;
adaptee->specificRequest();
std::cout << "Adapter: Postprocessing..." << std::endl;
}
};

3.1.7 性能分析

时间复杂度
  • 适配器方法调用:O(1),只是简单的方法转发
  • 智能适配器:O(1) + 额外逻辑的时间复杂度
  • 双向适配器:O(1),双向调用都是直接转发
空间复杂度
  • 类适配器:O(1),不需要额外存储被适配对象的引用
  • 对象适配器:O(1),需要存储一个被适配对象的引用
  • 智能适配器:O(1) + 额外状态的空间复杂度
性能优化策略
  1. 内联适配方法:对于简单的适配逻辑,可以使用内联方法减少函数调用开销
  2. 缓存适配结果:对于计算密集型的适配操作,可以缓存结果
  3. 延迟初始化:使用懒加载方式初始化适配器,减少启动时间
  4. 避免递归适配:确保适配器不会导致无限递归调用

3.1.8 优缺点

优点:

  • 复用性:复用已有的类,不需要修改原有代码
  • 兼容性:解决接口不兼容的问题,实现系统集成
  • 扩展性:符合开闭原则,对扩展开放,对修改关闭
  • 灵活性:可以通过组合方式适配多个对象
  • 透明性:客户端可以统一使用目标接口,无需知道适配过程

缺点:

  • 复杂度:增加了代码复杂度,引入了额外的类
  • 性能开销:适配过程可能会引入轻微的性能开销
  • 维护成本:需要维护适配器代码,特别是当被适配的类发生变化时
  • 调试难度:适配层可能会增加调试的复杂性

3.1.9 应用场景

适合使用适配器模式的场景:

  1. 集成第三方库

    • 当第三方库的接口与项目规范不兼容时
    • 当需要隔离第三方库的变化时
    • 当需要统一多个第三方库的接口时
  2. 跨平台开发

    • 为不同平台的 API 提供统一接口
    • 处理平台特定的功能差异
    • 实现代码的平台无关性
  3. 系统重构

    • 渐进式替换旧系统的接口
    • 保持新旧系统的兼容性
    • 减少重构对现有代码的影响
  4. 接口标准化

    • 为不同模块提供统一的接口标准
    • 隐藏内部实现的差异
    • 提高系统的一致性和可维护性

实际应用案例:

1. 日志系统适配

场景:集成不同的日志库,如 log4j、slf4j、logback 等,提供统一的日志接口。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 目标接口
public interface Logger {
void debug(String message);
void info(String message);
void warn(String message);
void error(String message);
}

// 被适配的类(log4j)
public class Log4jLogger {
private org.apache.log4j.Logger logger;

public Log4jLogger(Class<?> clazz) {
logger = org.apache.log4j.Logger.getLogger(clazz);
}

public void logDebug(String message) {
logger.debug(message);
}

public void logInfo(String message) {
logger.info(message);
}

public void logWarn(String message) {
logger.warn(message);
}

public void logError(String message) {
logger.error(message);
}
}

// 适配器类
public class Log4jAdapter implements Logger {
private Log4jLogger adaptee;

public Log4jAdapter(Class<?> clazz) {
adaptee = new Log4jLogger(clazz);
}

@Override
public void debug(String message) {
adaptee.logDebug(message);
}

@Override
public void info(String message) {
adaptee.logInfo(message);
}

@Override
public void warn(String message) {
adaptee.logWarn(message);
}

@Override
public void error(String message) {
adaptee.logError(message);
}
}

// 客户端使用
public class Client {
private static final Logger logger = new Log4jAdapter(Client.class);

public static void main(String[] args) {
logger.info("Application started");
// 业务逻辑
logger.debug("Debug information");
logger.error("Error occurred");
}
}
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 目标接口
class DatabaseConnection {
public:
virtual ~DatabaseConnection() = default;
virtual void connect() = 0;
virtual void disconnect() = 0;
virtual void executeQuery(const std::string& query) = 0;
};

// 被适配的类(MySQL)
class MySQLConnection {
public:
void mysqlConnect() {
std::cout << "Connecting to MySQL database" << std::endl;
}

void mysqlDisconnect() {
std::cout << "Disconnecting from MySQL database" << std::endl;
}

void mysqlExecute(const std::string& query) {
std::cout << "Executing MySQL query: " << query << std::endl;
}
};

// 适配器类
class MySQLAdapter : public DatabaseConnection {
private:
std::unique_ptr<MySQLConnection> adaptee;
public:
MySQLAdapter() : adaptee(std::make_unique<MySQLConnection>()) {
}

void connect() override {
adaptee->mysqlConnect();
}

void disconnect() override {
adaptee->mysqlDisconnect();
}

void executeQuery(const std::string& query) override {
adaptee->mysqlExecute(query);
}
};

// 客户端使用
int main() {
std::unique_ptr<DatabaseConnection> db = std::make_unique<MySQLAdapter>();
db->connect();
db->executeQuery("SELECT * FROM users");
db->disconnect();
return 0;
}
3. GUI 组件适配

场景:适配不同平台的 GUI 组件,提供统一的界面接口。

实现:

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
38
39
40
41
42
43
44
// 目标接口
public interface Button {
void render();
void onClick();
}

// 被适配的类(Windows 按钮)
public class WindowsButton {
public void paint() {
System.out.println("Rendering Windows button");
}

public void handleClick() {
System.out.println("Windows button clicked");
}
}

// 适配器类
public class WindowsButtonAdapter implements Button {
private WindowsButton adaptee;

public WindowsButtonAdapter(WindowsButton adaptee) {
this.adaptee = adaptee;
}

@Override
public void render() {
adaptee.paint();
}

@Override
public void onClick() {
adaptee.handleClick();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Button button = new WindowsButtonAdapter(new WindowsButton());
button.render();
button.onClick();
}
}

3.1.10 最佳实践

1. 适配器选择策略

类适配器 vs 对象适配器

特性类适配器对象适配器
实现方式多重继承组合
灵活性较低,只能适配特定类较高,可以适配任何实现了被适配接口的类
代码复杂度较低较高
适配能力只能适配一个类可以适配多个类
适用场景适配固定的类,不需要运行时切换需要运行时切换被适配对象,或适配多个类
2. 适配器实现技巧

Java 实现技巧

  1. 使用接口分离原则

    • 将目标接口拆分为多个小接口,提高灵活性
    • 客户端只依赖于需要的接口部分
  2. 使用泛型适配器

    • 实现通用的适配器模板,减少重复代码
    • 提高代码的可重用性
  3. 异常处理

    • 适配异常类型,确保客户端收到一致的异常
    • 提供详细的错误信息,便于调试

C++ 实现技巧

  1. 使用模板适配器

    • 利用模板实现类型无关的适配器
    • 减少运行时开销
  2. 智能指针管理

    • 使用 std::unique_ptrstd::shared_ptr 管理资源
    • 避免内存泄漏
  3. 完美转发

    • 使用 std::forward 实现参数的完美转发
    • 减少不必要的拷贝
3. 模式组合策略

与工厂方法模式结合

  • 使用工厂方法创建适配器实例
  • 根据运行时条件选择合适的适配器

与单例模式结合

  • 适配器实例作为单例,避免重复创建
  • 适用于全局配置的适配器

与装饰器模式结合

  • 在适配过程中添加额外的功能
  • 如日志、缓存、性能监控等

与策略模式结合

  • 将适配策略抽象为接口
  • 运行时选择不同的适配策略
4. 代码设计最佳实践

命名规范

  • 适配器类名:XxxAdapterXxxWrapper
  • 目标接口:Target 或具体业务名称
  • 被适配类:Adaptee 或具体实现名称

包结构组织

  • 将适配器相关类放在同一包或模块中
  • 按功能划分:核心适配器、工厂、工具类
  • 保持包结构清晰,便于维护

文档和注释

  • 为适配器添加详细的注释,说明适配的目的和实现细节
  • 记录被适配接口和目标接口的对应关系
  • 说明适配器的适用场景和限制

错误处理

  • 适配器应优雅处理被适配对象的异常
  • 提供一致的错误处理机制
  • 实现容错机制,确保系统稳定性
5. 测试策略

单元测试

  • 测试适配器是否正确转换接口调用
  • 验证适配器对异常的处理
  • 测试边界情况和特殊输入

集成测试

  • 测试适配器与被适配系统的集成
  • 验证适配器在实际场景中的表现
  • 测试不同配置下的适配效果

性能测试

  • 测量适配器的性能开销
  • 评估适配过程对系统整体性能的影响
  • 优化适配逻辑,减少性能损失

边界测试

  • 测试空对象的适配
  • 验证适配器对无效输入的处理
  • 测试并发环境下的适配器行为

3.1.11 与其他模式的关系

1. 适配器模式 vs 装饰器模式

核心区别

  • 目的:适配器模式用于接口转换,装饰器模式用于功能增强
  • 接口:适配器模式改变接口,装饰器模式保持接口不变
  • 关系:适配器模式是单向的,装饰器模式可以嵌套组合

适用场景对比

  • 适配器模式:需要使不兼容的接口一起工作
  • 装饰器模式:需要动态添加功能,不改变接口

组合使用

  • 先适配接口,再装饰功能
  • 适用于需要同时解决接口不兼容和功能增强的场景
2. 适配器模式 vs 代理模式

核心区别

  • 目的:适配器模式用于接口转换,代理模式用于控制访问
  • 接口:适配器模式改变接口,代理模式保持接口不变
  • 关系:适配器模式是对象的包装,代理模式是对象的代表

适用场景对比

  • 适配器模式:需要使不兼容的接口一起工作
  • 代理模式:需要控制对对象的访问,如权限检查、懒加载等

组合使用

  • 代理可以代理适配器,控制对适配对象的访问
  • 适用于需要同时解决接口不兼容和访问控制的场景
3. 适配器模式 vs 外观模式

核心区别

  • 目的:适配器模式用于接口转换,外观模式用于简化接口
  • 范围:适配器模式处理单个接口,外观模式处理多个接口
  • 关系:适配器模式是一对一的转换,外观模式是多对一的简化

适用场景对比

  • 适配器模式:需要使不兼容的接口一起工作
  • 外观模式:需要为复杂子系统提供简单接口

组合使用

  • 外观模式可以使用适配器来集成不同的子系统
  • 适用于需要同时简化接口和解决兼容性问题的场景
4. 适配器模式 vs 策略模式

核心区别

  • 目的:适配器模式用于接口转换,策略模式用于算法替换
  • 接口:适配器模式改变接口,策略模式保持接口不变
  • 关系:适配器模式是静态的转换,策略模式是动态的选择

适用场景对比

  • 适配器模式:需要使不兼容的接口一起工作
  • 策略模式:需要在运行时选择不同的算法或行为

组合使用

  • 策略模式可以使用适配器来适配不同的算法实现
  • 适用于需要同时支持多种算法和解决兼容性问题的场景
5. 模式选择指南

何时选择适配器模式

  • 需要集成不兼容的接口
  • 需要复用现有代码,避免修改
  • 需要统一不同系统的接口规范
  • 需要渐进式重构旧系统

何时选择其他模式

  • 装饰器模式:需要动态添加功能,不改变接口
  • 代理模式:需要控制对对象的访问
  • 外观模式:需要为复杂子系统提供简单接口
  • 策略模式:需要在运行时选择不同的算法或行为

模式组合建议

  • 适配器 + 工厂:动态创建合适的适配器
  • 适配器 + 装饰器:适配接口后增强功能
  • 适配器 + 外观:为复杂子系统提供统一接口
  • 适配器 + 策略:适配不同的算法实现

实际应用中的决策流程

  1. 分析接口不兼容的原因和范围
  2. 评估修改现有代码的成本和风险
  3. 选择合适的适配器类型(类适配器或对象适配器)
  4. 设计适配器的接口和实现
  5. 测试适配器的功能和性能
  6. 监控适配器在生产环境中的表现

3.2 桥接模式(Bridge)

3.2.1 意图

将抽象部分与它的实现部分分离,使它们都可以独立地变化。桥接模式通过组合而非继承的方式,实现了抽象和实现的解耦。

3.2.2 动机

当一个类的抽象部分和实现部分都需要独立变化时,可以使用桥接模式来解决这个问题。这种场景在以下情况尤为常见:

  • 图形界面中的窗口和其实现方式(不同的操作系统)
  • 跨平台应用的抽象和平台特定实现
  • 产品类层次和实现类层次的分离
  • 需要在运行时动态切换实现策略

桥接模式的核心动机是避免抽象和实现之间的永久绑定,使它们可以独立演化,从而减少代码重复和类爆炸问题。

3.2.3 结构

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
+----------------+
| Abstraction |
+----------------+
| - implementor: |
| Implementor |
| + operation() |
+----------------+
^
|
+----------------+
| RefinedAbstraction|
+----------------+
| + operation() |
| + extendedOperation()|
+----------------+

+----------------+
| Implementor |
+----------------+
| + operationImpl()|
+----------------+
^
|
+----------------+
| ConcreteImplementorA|
+----------------+
| + operationImpl()|
+----------------+
^
|
+----------------+
| ConcreteImplementorB|
+----------------+
| + operationImpl()|
+----------------+

3.2.4 参与者

  • Abstraction:定义抽象接口,包含一个对 Implementor 的引用,负责定义抽象部分的行为
  • RefinedAbstraction:扩展 Abstraction 的接口,添加额外的功能
  • Implementor:定义实现接口,负责定义实现部分的行为
  • ConcreteImplementor:实现 Implementor 接口,提供具体的实现

3.2.5 实现

Java 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 实现接口
public interface Implementor {
void operationImpl();
}

// 具体实现
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorA operationImpl");
}
}

public class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorB operationImpl");
}
}

// 抽象类
public abstract class Abstraction {
protected Implementor implementor;

public Abstraction(Implementor implementor) {
this.implementor = implementor;
}

public abstract void operation();
}

// 扩展抽象类
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}

@Override
public void operation() {
System.out.println("RefinedAbstraction operation");
implementor.operationImpl();
}

public void extendedOperation() {
System.out.println("RefinedAbstraction extended operation");
implementor.operationImpl();
System.out.println("Extended operation completed");
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Implementor implementorA = new ConcreteImplementorA();
Abstraction abstractionA = new RefinedAbstraction(implementorA);
abstractionA.operation();
((RefinedAbstraction) abstractionA).extendedOperation();

Implementor implementorB = new ConcreteImplementorB();
Abstraction abstractionB = new RefinedAbstraction(implementorB);
abstractionB.operation();
((RefinedAbstraction) abstractionB).extendedOperation();
}
}
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 实现接口
class Implementor {
public:
virtual ~Implementor() = default;
virtual void operationImpl() = 0;
};

// 具体实现
class ConcreteImplementorA : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorA operationImpl" << std::endl;
}
};

class ConcreteImplementorB : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorB operationImpl" << std::endl;
}
};

// 抽象类
class Abstraction {
protected:
Implementor* implementor;
public:
Abstraction(Implementor* implementor) : implementor(implementor) {
}

virtual ~Abstraction() {
}

virtual void operation() = 0;
};

// 扩展抽象类
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(Implementor* implementor) : Abstraction(implementor) {
}

void operation() override {
std::cout << "RefinedAbstraction operation" << std::endl;
implementor->operationImpl();
}

void extendedOperation() {
std::cout << "RefinedAbstraction extended operation" << std::endl;
implementor->operationImpl();
std::cout << "Extended operation completed" << std::endl;
}
};

// 客户端使用
int main() {
Implementor* implementorA = new ConcreteImplementorA();
Abstraction* abstractionA = new RefinedAbstraction(implementorA);
abstractionA->operation();
static_cast<RefinedAbstraction*>(abstractionA)->extendedOperation();

Implementor* implementorB = new ConcreteImplementorB();
Abstraction* abstractionB = new RefinedAbstraction(implementorB);
abstractionB->operation();
static_cast<RefinedAbstraction*>(abstractionB)->extendedOperation();

delete abstractionA;
delete implementorA;
delete abstractionB;
delete implementorB;

return 0;
}

现代 C++ 实现(使用智能指针):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <memory>

// 实现接口
class Implementor {
public:
virtual ~Implementor() = default;
virtual void operationImpl() = 0;
};

// 具体实现
class ConcreteImplementorA : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorA operationImpl" << std::endl;
}
};

class ConcreteImplementorB : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorB operationImpl" << std::endl;
}
};

// 抽象类
class Abstraction {
protected:
std::unique_ptr<Implementor> implementor;
public:
Abstraction(std::unique_ptr<Implementor> implementor) : implementor(std::move(implementor)) {
}

virtual ~Abstraction() = default;

virtual void operation() = 0;
};

// 扩展抽象类
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(std::unique_ptr<Implementor> implementor) : Abstraction(std::move(implementor)) {
}

void operation() override {
std::cout << "RefinedAbstraction operation" << std::endl;
implementor->operationImpl();
}

void extendedOperation() {
std::cout << "RefinedAbstraction extended operation" << std::endl;
implementor->operationImpl();
std::cout << "Extended operation completed" << std::endl;
}
};

// 客户端使用
int main() {
auto implementorA = std::make_unique<ConcreteImplementorA>();
std::unique_ptr<Abstraction> abstractionA = std::make_unique<RefinedAbstraction>(std::move(implementorA));
abstractionA->operation();
static_cast<RefinedAbstraction*>(abstractionA.get())->extendedOperation();

auto implementorB = std::make_unique<ConcreteImplementorB>();
std::unique_ptr<Abstraction> abstractionB = std::make_unique<RefinedAbstraction>(std::move(implementorB));
abstractionB->operation();
static_cast<RefinedAbstraction*>(abstractionB.get())->extendedOperation();

return 0;
}

3.2.6 实现变体

1. 多维度桥接

当抽象和实现都有多个维度的变化时,可以使用多维度桥接模式。

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
// 实现接口1
public interface Implementor1 {
void operation1();
}

// 实现接口2
public interface Implementor2 {
void operation2();
}

// 抽象类
public abstract class Abstraction {
protected Implementor1 implementor1;
protected Implementor2 implementor2;

public Abstraction(Implementor1 implementor1, Implementor2 implementor2) {
this.implementor1 = implementor1;
this.implementor2 = implementor2;
}

public abstract void operation();
}

// 扩展抽象类
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor1 implementor1, Implementor2 implementor2) {
super(implementor1, implementor2);
}

@Override
public void operation() {
implementor1.operation1();
implementor2.operation2();
}
}
2. 动态桥接

在运行时动态切换实现,提供更大的灵活性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Abstraction {
private:
std::unique_ptr<Implementor> implementor;
public:
Abstraction(std::unique_ptr<Implementor> implementor) : implementor(std::move(implementor)) {
}

void setImplementor(std::unique_ptr<Implementor> newImplementor) {
implementor = std::move(newImplementor);
}

void operation() {
implementor->operationImpl();
}
};
3. 智能桥接

在桥接模式中添加智能特性,如缓存、日志、错误处理等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SmartAbstraction extends Abstraction {
private Map<String, String> cache = new HashMap<>();

public SmartAbstraction(Implementor implementor) {
super(implementor);
}

@Override
public void operation() {
String key = "operation";
if (cache.containsKey(key)) {
System.out.println("Using cached result: " + cache.get(key));
return;
}

System.out.println("Executing operation...");
implementor.operationImpl();
cache.put(key, "completed");
}
}

3.2.7 性能分析

时间复杂度
  • 抽象方法调用:O(1),直接调用实现方法
  • 扩展方法调用:O(1) + 额外操作的时间复杂度
  • 实现切换:O(1),只是指针或引用的赋值
空间复杂度
  • 抽象部分:O(1),存储一个实现引用
  • 实现部分:O(1),根据具体实现而定
  • 多维度桥接:O(n),n 是实现维度的数量
性能优化策略
  1. 内联方法:对于简单的桥接调用,可以使用内联方法减少函数调用开销
  2. 缓存实现:对于频繁切换的实现,可以缓存常用的实现实例
  3. 延迟初始化:使用懒加载方式初始化实现,减少启动时间
  4. 避免递归调用:确保桥接调用不会导致无限递归

3.2.8 优缺点

优点:

  • 解耦抽象和实现:使它们可以独立变化,提高系统的灵活性
  • 减少子类数量:避免了抽象和实现的组合爆炸问题
  • 提高可扩展性:可以独立添加新的抽象和实现
  • 运行时切换:支持在运行时动态切换实现
  • 符合开闭原则:对扩展开放,对修改关闭

缺点:

  • 增加复杂度:引入了额外的抽象层,增加了代码复杂度
  • 理解难度:需要正确识别系统中的抽象和实现部分
  • 性能开销:桥接调用可能会引入轻微的性能开销
  • 设计要求高:需要合理设计抽象和实现的分离

3.2.9 应用场景

适合使用桥接模式的场景:

  1. 跨平台开发

    • 为不同平台提供统一的抽象接口
    • 如 GUI 库、数据库驱动、网络协议等
  2. 产品系列设计

    • 分离产品的抽象和具体实现
    • 如不同型号的手机及其硬件实现
  3. 插件系统

    • 定义插件接口,允许动态加载不同的实现
    • 如 IDE 的插件架构
  4. 图形系统

    • 分离图形对象的抽象和渲染实现
    • 如不同的渲染引擎
  5. 业务系统

    • 分离业务逻辑的抽象和具体实现
    • 如不同的支付方式、物流策略等

实际应用案例:

1. GUI 系统

场景:开发跨平台的 GUI 库,支持不同操作系统的窗口实现。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// 实现接口
public interface WindowImpl {
void drawWindow(int x, int y, int width, int height, String title);
void drawButton(int x, int y, int width, int height, String label);
void drawText(int x, int y, String text);
}

// Windows 实现
public class WindowsWindowImpl implements WindowImpl {
@Override
public void drawWindow(int x, int y, int width, int height, String title) {
System.out.println("Windows: Drawing window at " + x + "," + y + " with size " + width + "x" + height + " titled " + title);
}

@Override
public void drawButton(int x, int y, int width, int height, String label) {
System.out.println("Windows: Drawing button at " + x + "," + y + " with size " + width + "x" + height + " labeled " + label);
}

@Override
public void drawText(int x, int y, String text) {
System.out.println("Windows: Drawing text at " + x + "," + y + ": " + text);
}
}

// macOS 实现
public class MacOSWindowImpl implements WindowImpl {
@Override
public void drawWindow(int x, int y, int width, int height, String title) {
System.out.println("macOS: Drawing window at " + x + "," + y + " with size " + width + "x" + height + " titled " + title);
}

@Override
public void drawButton(int x, int y, int width, int height, String label) {
System.out.println("macOS: Drawing button at " + x + "," + y + " with size " + width + "x" + height + " labeled " + label);
}

@Override
public void drawText(int x, int y, String text) {
System.out.println("macOS: Drawing text at " + x + "," + y + ": " + text);
}
}

// 抽象类
public abstract class Window {
protected WindowImpl impl;

public Window(WindowImpl impl) {
this.impl = impl;
}

public abstract void draw();
public abstract void handleEvent(String event);
}

// 具体窗口
public class ApplicationWindow extends Window {
private String title;
private int x, y, width, height;

public ApplicationWindow(WindowImpl impl, String title, int x, int y, int width, int height) {
super(impl);
this.title = title;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

@Override
public void draw() {
impl.drawWindow(x, y, width, height, title);
impl.drawButton(x + 10, y + 30, 100, 30, "OK");
impl.drawButton(x + 120, y + 30, 100, 30, "Cancel");
impl.drawText(x + 10, y + 70, "Welcome to the application!");
}

@Override
public void handleEvent(String event) {
if (event.equals("OK")) {
System.out.println("OK button clicked");
} else if (event.equals("Cancel")) {
System.out.println("Cancel button clicked");
}
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// Windows 平台
WindowImpl windowsImpl = new WindowsWindowImpl();
Window windowsWindow = new ApplicationWindow(windowsImpl, "Windows App", 100, 100, 400, 300);
windowsWindow.draw();
windowsWindow.handleEvent("OK");

// macOS 平台
WindowImpl macOSImpl = new MacOSWindowImpl();
Window macOSWindow = new ApplicationWindow(macOSImpl, "macOS App", 100, 100, 400, 300);
macOSWindow.draw();
macOSWindow.handleEvent("Cancel");
}
}
2. 数据库访问系统

场景:开发支持多种数据库的访问系统,分离 SQL 抽象和具体数据库实现。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 实现接口
class DatabaseImpl {
public:
virtual ~DatabaseImpl() = default;
virtual void connect(const std::string& connectionString) = 0;
virtual void disconnect() = 0;
virtual void execute(const std::string& query) = 0;
};

// MySQL 实现
class MySQLImpl : public DatabaseImpl {
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to MySQL: " << connectionString << std::endl;
}

void disconnect() override {
std::cout << "Disconnecting from MySQL" << std::endl;
}

void execute(const std::string& query) override {
std::cout << "Executing MySQL query: " << query << std::endl;
}
};

// PostgreSQL 实现
class PostgreSQLImpl : public DatabaseImpl {
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to PostgreSQL: " << connectionString << std::endl;
}

void disconnect() override {
std::cout << "Disconnecting from PostgreSQL" << std::endl;
}

void execute(const std::string& query) override {
std::cout << "Executing PostgreSQL query: " << query << std::endl;
}
};

// 抽象类
class Database {
protected:
std::unique_ptr<DatabaseImpl> impl;
public:
Database(std::unique_ptr<DatabaseImpl> impl) : impl(std::move(impl)) {
}

virtual void connect(const std::string& connectionString) = 0;
virtual void disconnect() = 0;
virtual void execute(const std::string& query) = 0;
};

// 具体数据库
class SqlDatabase : public Database {
public:
SqlDatabase(std::unique_ptr<DatabaseImpl> impl) : Database(std::move(impl)) {
}

void connect(const std::string& connectionString) override {
impl->connect(connectionString);
}

void disconnect() override {
impl->disconnect();
}

void execute(const std::string& query) override {
impl->execute(query);
}

// 扩展方法
void executeBatch(const std::vector<std::string>& queries) {
for (const auto& query : queries) {
impl->execute(query);
}
}
};

// 客户端使用
int main() {
// MySQL 数据库
auto mysqlImpl = std::make_unique<MySQLImpl>();
std::unique_ptr<Database> mysqlDb = std::make_unique<SqlDatabase>(std::move(mysqlImpl));
mysqlDb->connect("localhost:3306/mydb");
mysqlDb->execute("SELECT * FROM users");
static_cast<SqlDatabase*>(mysqlDb.get())->executeBatch({"INSERT INTO users (name) VALUES ('Alice')", "INSERT INTO users (name) VALUES ('Bob')"});
mysqlDb->disconnect();

// PostgreSQL 数据库
auto postgresImpl = std::make_unique<PostgreSQLImpl>();
std::unique_ptr<Database> postgresDb = std::make_unique<SqlDatabase>(std::move(postgresImpl));
postgresDb->connect("localhost:5432/mydb");
postgresDb->execute("SELECT * FROM users");
postgresDb->disconnect();

return 0;
}
3. 图形渲染系统

场景:开发支持多种渲染引擎的图形系统,分离图形抽象和具体渲染实现。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 实现接口
public interface Renderer {
void renderCircle(double x, double y, double radius);
void renderRectangle(double x, double y, double width, double height);
void renderText(double x, double y, String text);
}

// OpenGL 实现
public class OpenGLRenderer implements Renderer {
@Override
public void renderCircle(double x, double y, double radius) {
System.out.println("OpenGL: Rendering circle at (" + x + ", " + y + ") with radius " + radius);
}

@Override
public void renderRectangle(double x, double y, double width, double height) {
System.out.println("OpenGL: Rendering rectangle at (" + x + ", " + y + ") with size " + width + "x" + height);
}

@Override
public void renderText(double x, double y, String text) {
System.out.println("OpenGL: Rendering text \"" + text + "\" at (" + x + ", " + y + ")");
}
}

// DirectX 实现
public class DirectXRenderer implements Renderer {
@Override
public void renderCircle(double x, double y, double radius) {
System.out.println("DirectX: Rendering circle at (" + x + ", " + y + ") with radius " + radius);
}

@Override
public void renderRectangle(double x, double y, double width, double height) {
System.out.println("DirectX: Rendering rectangle at (" + x + ", " + y + ") with size " + width + "x" + height);
}

@Override
public void renderText(double x, double y, String text) {
System.out.println("DirectX: Rendering text \"" + text + "\" at (" + x + ", " + y + ")");
}
}

// 抽象类
public abstract class Shape {
protected Renderer renderer;

public Shape(Renderer renderer) {
this.renderer = renderer;
}

public abstract void draw();
}

// 具体形状
public class Circle extends Shape {
private double x, y, radius;

public Circle(Renderer renderer, double x, double y, double radius) {
super(renderer);
this.x = x;
this.y = y;
this.radius = radius;
}

@Override
public void draw() {
renderer.renderCircle(x, y, radius);
}
}

public class Rectangle extends Shape {
private double x, y, width, height;

public Rectangle(Renderer renderer, double x, double y, double width, double height) {
super(renderer);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}

@Override
public void draw() {
renderer.renderRectangle(x, y, width, height);
}
}

public class Text extends Shape {
private double x, y;
private String text;

public Text(Renderer renderer, double x, double y, String text) {
super(renderer);
this.x = x;
this.y = y;
this.text = text;
}

@Override
public void draw() {
renderer.renderText(x, y, text);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// OpenGL 渲染
Renderer openGLRenderer = new OpenGLRenderer();
Shape circle1 = new Circle(openGLRenderer, 100, 100, 50);
Shape rectangle1 = new Rectangle(openGLRenderer, 200, 200, 100, 80);
Shape text1 = new Text(openGLRenderer, 150, 300, "Hello OpenGL!");

circle1.draw();
rectangle1.draw();
text1.draw();

// DirectX 渲染
Renderer directXRenderer = new DirectXRenderer();
Shape circle2 = new Circle(directXRenderer, 100, 100, 50);
Shape rectangle2 = new Rectangle(directXRenderer, 200, 200, 100, 80);
Shape text2 = new Text(directXRenderer, 150, 300, "Hello DirectX!");

circle2.draw();
rectangle2.draw();
text2.draw();
}
}

3.2.10 最佳实践

1. 桥接策略选择

单一桥接 vs 多维度桥接

特性单一桥接多维度桥接
复杂度较低较高
灵活性一般较高
适用场景单一实现维度多个实现维度
维护成本较低较高
2. 桥接实现技巧

Java 实现技巧

  1. 使用接口分离原则

    • 将实现接口拆分为多个小接口,提高灵活性
    • 客户端只依赖于需要的接口部分
  2. 使用依赖注入

    • 通过构造函数或 setter 方法注入实现
    • 提高代码的可测试性和可维护性
  3. 异常处理

    • 在桥接调用中正确处理异常
    • 确保异常能够正确传递给客户端

C++ 实现技巧

  1. 智能指针管理

    • 使用 std::unique_ptrstd::shared_ptr 管理实现对象
    • 避免内存泄漏和悬垂指针
  2. 模板特化

    • 使用模板实现通用的桥接逻辑
    • 为特定类型提供特化实现
  3. 完美转发

    • 使用 std::forward 实现参数的完美转发
    • 减少不必要的拷贝
3. 模式组合策略

与工厂方法模式结合

  • 使用工厂方法创建具体的实现实例
  • 根据运行时条件选择合适的实现

与单例模式结合

  • 实现实例作为单例,避免重复创建
  • 适用于全局配置的实现

与装饰器模式结合

  • 在实现中添加额外的功能
  • 如日志、缓存、性能监控等

与策略模式结合

  • 将实现策略抽象为接口
  • 运行时选择不同的实现策略
4. 代码设计最佳实践

命名规范

  • 抽象类名:Abstraction 或具体业务名称
  • 实现接口:Implementor 或具体实现名称
  • 具体实现:ConcreteImplementorX 或具体平台/技术名称

包结构组织

  • 将桥接相关类放在同一包或模块中
  • 按功能划分:抽象层、实现层、工厂
  • 保持包结构清晰,便于维护

文档和注释

  • 为桥接模式添加详细的注释,说明抽象和实现的分离目的
  • 记录抽象层和实现层的对应关系
  • 说明桥接模式的适用场景和限制

错误处理

  • 实现应优雅处理运行时异常
  • 提供一致的错误处理机制
  • 实现容错机制,确保系统稳定性
5. 测试策略

单元测试

  • 测试抽象层的方法是否正确调用实现层
  • 验证不同实现的行为是否符合预期
  • 测试边界情况和特殊输入

集成测试

  • 测试抽象层与实现层的集成
  • 验证桥接模式在实际场景中的表现
  • 测试不同配置下的桥接效果

性能测试

  • 测量桥接调用的性能开销
  • 评估桥接模式对系统整体性能的影响
  • 优化桥接逻辑,减少性能损失

边界测试

  • 测试空实现的处理
  • 验证桥接对无效输入的处理
  • 测试并发环境下的桥接行为

3.2.11 与其他模式的关系

1. 桥接模式 vs 适配器模式

核心区别

  • 目的:桥接模式用于分离抽象和实现,适配器模式用于接口转换
  • 时机:桥接模式是设计时考虑的,适配器模式是后期集成时考虑的
  • 关系:桥接模式是双向的,适配器模式是单向的

适用场景对比

  • 桥接模式:抽象和实现都需要独立变化
  • 适配器模式:需要集成不兼容的接口

组合使用

  • 桥接模式的实现部分可以使用适配器模式来集成现有系统
  • 适用于需要同时分离抽象和实现,以及集成不兼容接口的场景
2. 桥接模式 vs 装饰器模式

核心区别

  • 目的:桥接模式用于分离抽象和实现,装饰器模式用于动态添加功能
  • 结构:桥接模式有两个独立的层次结构,装饰器模式是单一层次结构的嵌套
  • 关系:桥接模式是组合关系,装饰器模式是包装关系

适用场景对比

  • 桥接模式:抽象和实现都需要独立变化
  • 装饰器模式:需要动态添加功能,不改变接口

组合使用

  • 桥接模式的实现部分可以使用装饰器模式来增强功能
  • 适用于需要同时分离抽象和实现,以及动态添加功能的场景
3. 桥接模式 vs 策略模式

核心区别

  • 目的:桥接模式用于分离抽象和实现,策略模式用于算法替换
  • 范围:桥接模式涉及整个类的结构,策略模式只涉及算法部分
  • 关系:桥接模式是长期的结构关系,策略模式是短期的算法选择

适用场景对比

  • 桥接模式:抽象和实现都需要独立变化
  • 策略模式:需要在运行时选择不同的算法或行为

组合使用

  • 桥接模式的实现部分可以使用策略模式来选择不同的算法
  • 适用于需要同时分离抽象和实现,以及选择不同算法的场景
4. 桥接模式 vs 抽象工厂模式

核心区别

  • 目的:桥接模式用于分离抽象和实现,抽象工厂模式用于创建一系列相关对象
  • 结构:桥接模式有两个独立的层次结构,抽象工厂模式是单一层次结构
  • 关系:桥接模式是组合关系,抽象工厂模式是创建关系

适用场景对比

  • 桥接模式:抽象和实现都需要独立变化
  • 抽象工厂模式:需要创建一系列相关或相互依赖的对象

组合使用

  • 桥接模式的实现部分可以使用抽象工厂模式来创建相关的实现对象
  • 适用于需要同时分离抽象和实现,以及创建相关对象的场景
5. 模式选择指南

何时选择桥接模式

  • 需要分离抽象和实现,使它们可以独立变化
  • 抽象和实现都有多个维度的变化
  • 需要避免抽象和实现之间的永久绑定
  • 需要在运行时动态切换实现

何时选择其他模式

  • 适配器模式:需要集成不兼容的接口
  • 装饰器模式:需要动态添加功能,不改变接口
  • 策略模式:需要在运行时选择不同的算法或行为
  • 抽象工厂模式:需要创建一系列相关或相互依赖的对象

模式组合建议

  • 桥接 + 工厂:动态创建合适的实现
  • 桥接 + 装饰器:分离抽象和实现后增强功能
  • 桥接 + 策略:分离抽象和实现后选择不同算法
  • 桥接 + 抽象工厂:分离抽象和实现后创建相关对象

实际应用中的决策流程

  1. 分析系统中是否存在抽象和实现需要独立变化的情况
  2. 评估抽象和实现的变化维度和频率
  3. 选择合适的桥接策略(单一桥接或多维度桥接)
  4. 设计抽象层和实现层的接口
  5. 实现具体的抽象和实现类
  6. 测试桥接模式的功能和性能
  7. 监控桥接模式在生产环境中的表现

3.3 组合模式(Composite)

3.3.1 意图

将对象组合成树形结构以表示「部分-整体」的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

3.3.2 动机

当需要处理树形结构时,组合模式可以让客户端统一处理单个节点和节点组合。这种场景在以下情况尤为常见:

  • 文件系统的目录和文件结构
  • 图形界面的组件层次
  • 组织结构的部门和员工关系
  • XML/JSON 等树形数据结构的处理
  • 菜单和子菜单的层次结构

组合模式的核心动机是通过统一接口来处理单个对象和组合对象,简化客户端代码,同时保持树形结构的灵活性和可扩展性。

3.3.3 结构

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
+----------------+
| Component |
+----------------+
| + operation() |
| + add(Component)|
| + remove(Component)|
| + getChild(int)|
| + getParent() |
| + isComposite()|
+----------------+
^
|
+----------------+ +----------------+
| Leaf | | Composite |
+----------------+ +----------------+
| + operation() | | + operation() |
| + add(Component)| | + add(Component)|
| + remove(Component)| | + remove(Component)|
| + getChild(int)| | + getChild(int)|
| + getParent() | | + getParent() |
| + isComposite()| | + isComposite()|
+----------------+ +----------------+
| - children: |
| List<Component>|
| - parent: |
| Component |
+----------------+

3.3.4 参与者

  • Component:定义组件的接口,包含管理子组件的方法,是组合模式的核心
  • Leaf:表示叶节点,没有子组件,实现 Component 接口
  • Composite:表示复合节点,包含子组件,实现 Component 接口

3.3.5 实现

Java 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 组件接口
public abstract class Component {
protected Component parent;

public abstract void operation();

public void add(Component component) {
throw new UnsupportedOperationException();
}

public void remove(Component component) {
throw new UnsupportedOperationException();
}

public Component getChild(int index) {
throw new UnsupportedOperationException();
}

public Component getParent() {
return parent;
}

public void setParent(Component parent) {
this.parent = parent;
}

public boolean isComposite() {
return false;
}
}

// 叶节点
public class Leaf extends Component {
private String name;

public Leaf(String name) {
this.name = name;
}

@Override
public void operation() {
System.out.println("Leaf " + name + " operation");
}
}

// 复合节点
public class Composite extends Component {
private List<Component> children = new ArrayList<>();
private String name;

public Composite(String name) {
this.name = name;
}

@Override
public void operation() {
System.out.println("Composite " + name + " operation");
for (Component child : children) {
child.operation();
}
}

@Override
public void add(Component component) {
children.add(component);
component.setParent(this);
}

@Override
public void remove(Component component) {
children.remove(component);
component.setParent(null);
}

@Override
public Component getChild(int index) {
return children.get(index);
}

@Override
public boolean isComposite() {
return true;
}

// 扩展方法
public int getChildCount() {
return children.size();
}

public void clear() {
for (Component child : children) {
child.setParent(null);
}
children.clear();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Composite root = new Composite("根");

Leaf leaf1 = new Leaf("叶1");
Leaf leaf2 = new Leaf("叶2");

Composite composite = new Composite("分支");
Leaf leaf3 = new Leaf("叶3");
Leaf leaf4 = new Leaf("叶4");

composite.add(leaf3);
composite.add(leaf4);

root.add(leaf1);
root.add(leaf2);
root.add(composite);

System.out.println("=== 执行操作 ===");
root.operation();

System.out.println("\n=== 测试组合操作 ===");
System.out.println("根节点子数量: " + root.getChildCount());
System.out.println("分支节点子数量: " + composite.getChildCount());
System.out.println("叶1是否为组合: " + leaf1.isComposite());
System.out.println("分支是否为组合: " + composite.isComposite());

System.out.println("\n=== 移除操作 ===");
root.remove(leaf2);
root.operation();

System.out.println("\n=== 清空操作 ===");
composite.clear();
root.operation();
}
}
C++ 实现

基础实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <vector>
#include <string>

// 组件接口
class Component {
protected:
Component* parent;
std::string name;
public:
Component(const std::string& name) : name(name), parent(nullptr) {
}

virtual ~Component() {
}

virtual void operation() = 0;

virtual void add(Component* component) {
throw std::runtime_error("Unsupported operation");
}

virtual void remove(Component* component) {
throw std::runtime_error("Unsupported operation");
}

virtual Component* getChild(int index) {
throw std::runtime_error("Unsupported operation");
}

virtual Component* getParent() {
return parent;
}

virtual void setParent(Component* parent) {
this->parent = parent;
}

virtual bool isComposite() {
return false;
}

const std::string& getName() {
return name;
}
};

// 叶节点
class Leaf : public Component {
public:
Leaf(const std::string& name) : Component(name) {
}

void operation() override {
std::cout << "Leaf " << name << " operation" << std::endl;
}
};

// 复合节点
class Composite : public Component {
private:
std::vector<Component*> children;
public:
Composite(const std::string& name) : Component(name) {
}

~Composite() {
for (Component* child : children) {
delete child;
}
}

void operation() override {
std::cout << "Composite " << name << " operation" << std::endl;
for (Component* child : children) {
child->operation();
}
}

void add(Component* component) override {
children.push_back(component);
component->setParent(this);
}

void remove(Component* component) override {
auto it = std::find(children.begin(), children.end(), component);
if (it != children.end()) {
(*it)->setParent(nullptr);
children.erase(it);
}
}

Component* getChild(int index) override {
if (index >= 0 && index < children.size()) {
return children[index];
}
return nullptr;
}

bool isComposite() override {
return true;
}

// 扩展方法
int getChildCount() {
return children.size();
}

void clear() {
for (Component* child : children) {
child->setParent(nullptr);
delete child;
}
children.clear();
}
};

// 客户端使用
int main() {
Composite* root = new Composite("根");

Leaf* leaf1 = new Leaf("叶1");
Leaf* leaf2 = new Leaf("叶2");

Composite* composite = new Composite("分支");
Leaf* leaf3 = new Leaf("叶3");
Leaf* leaf4 = new Leaf("叶4");

composite->add(leaf3);
composite->add(leaf4);

root->add(leaf1);
root->add(leaf2);
root->add(composite);

std::cout << "=== 执行操作 ===" << std::endl;
root->operation();

std::cout << "\n=== 测试组合操作 ===" << std::endl;
std::cout << "根节点子数量: " << root->getChildCount() << std::endl;
std::cout << "分支节点子数量: " << composite->getChildCount() << std::endl;
std::cout << "叶1是否为组合: " << std::boolalpha << leaf1->isComposite() << std::endl;
std::cout << "分支是否为组合: " << std::boolalpha << composite->isComposite() << std::endl;

std::cout << "\n=== 移除操作 ===" << std::endl;
root->remove(leaf2);
root->operation();

std::cout << "\n=== 清空操作 ===" << std::endl;
composite->clear();
root->operation();

delete root;
return 0;
}

现代 C++ 实现(使用智能指针):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <iostream>
#include <vector>
#include <string>
#include <memory>

// 组件接口
class Component {
protected:
Component* parent;
std::string name;
public:
Component(const std::string& name) : name(name), parent(nullptr) {
}

virtual ~Component() = default;

virtual void operation() = 0;

virtual void add(std::unique_ptr<Component> component) {
throw std::runtime_error("Unsupported operation");
}

virtual void remove(Component* component) {
throw std::runtime_error("Unsupported operation");
}

virtual Component* getChild(int index) {
throw std::runtime_error("Unsupported operation");
}

virtual Component* getParent() {
return parent;
}

virtual void setParent(Component* parent) {
this->parent = parent;
}

virtual bool isComposite() {
return false;
}

const std::string& getName() {
return name;
}
};

// 叶节点
class Leaf : public Component {
public:
Leaf(const std::string& name) : Component(name) {
}

void operation() override {
std::cout << "Leaf " << name << " operation" << std::endl;
}
};

// 复合节点
class Composite : public Component {
private:
std::vector<std::unique_ptr<Component>> children;
public:
Composite(const std::string& name) : Component(name) {
}

void operation() override {
std::cout << "Composite " << name << " operation" << std::endl;
for (const auto& child : children) {
child->operation();
}
}

void add(std::unique_ptr<Component> component) override {
component->setParent(this);
children.push_back(std::move(component));
}

void remove(Component* component) override {
auto it = std::find_if(children.begin(), children.end(),
[component](const std::unique_ptr<Component>& c) {
return c.get() == component;
});
if (it != children.end()) {
(*it)->setParent(nullptr);
children.erase(it);
}
}

Component* getChild(int index) override {
if (index >= 0 && index < children.size()) {
return children[index].get();
}
return nullptr;
}

bool isComposite() override {
return true;
}

// 扩展方法
int getChildCount() {
return children.size();
}

void clear() {
for (auto& child : children) {
child->setParent(nullptr);
}
children.clear();
}
};

// 客户端使用
int main() {
auto root = std::make_unique<Composite>("根");

auto leaf1 = std::make_unique<Leaf>("叶1");
auto leaf2 = std::make_unique<Leaf>("叶2");

auto composite = std::make_unique<Composite>("分支");
auto leaf3 = std::make_unique<Leaf>("叶3");
auto leaf4 = std::make_unique<Leaf>("叶4");

composite->add(std::move(leaf3));
composite->add(std::move(leaf4));

root->add(std::move(leaf1));
root->add(std::move(leaf2));
root->add(std::move(composite));

std::cout << "=== 执行操作 ===" << std::endl;
root->operation();

std::cout << "\n=== 测试组合操作 ===" << std::endl;
std::cout << "根节点子数量: " << root->getChildCount() << std::endl;

// 注意:这里不能直接访问 composite,因为它已经被移动到 root 中
// 实际应用中,可能需要通过 getChild 来获取

std::cout << "\n=== 执行操作 ===" << std::endl;
root->operation();

return 0;
}

3.3.6 实现变体

1. 安全组合模式

在安全组合模式中,Component 接口只定义基本操作,不包含子组件管理方法,这些方法只在 Composite 类中定义。

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
// 组件接口
public abstract class Component {
public abstract void operation();
}

// 叶节点
public class Leaf extends Component {
@Override
public void operation() {
// 实现
}
}

// 复合节点
public class Composite extends Component {
private List<Component> children = new ArrayList<>();

@Override
public void operation() {
// 实现
}

public void add(Component component) {
children.add(component);
}

public void remove(Component component) {
children.remove(component);
}

public Component getChild(int index) {
return children.get(index);
}
}
2. 透明组合模式

在透明组合模式中,Component 接口包含所有子组件管理方法,Leaf 类通过抛出异常来拒绝这些操作。

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
// 组件接口
public abstract class Component {
public abstract void operation();
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract Component getChild(int index);
}

// 叶节点
public class Leaf extends Component {
@Override
public void operation() {
// 实现
}

@Override
public void add(Component component) {
throw new UnsupportedOperationException();
}

@Override
public void remove(Component component) {
throw new UnsupportedOperationException();
}

@Override
public Component getChild(int index) {
throw new UnsupportedOperationException();
}
}
3. 智能组合模式

在智能组合模式中,添加智能特性,如缓存、懒加载、事件通知等。

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
public class SmartComposite extends Composite {
private Map<String, Component> componentMap = new HashMap<>();
private boolean initialized = false;

@Override
public void operation() {
if (!initialized) {
initialize();
}
super.operation();
}

private void initialize() {
System.out.println("Initializing composite...");
// 懒加载子组件
initialized = true;
}

@Override
public void add(Component component) {
super.add(component);
componentMap.put(component.getName(), component);
}

public Component getComponentByName(String name) {
return componentMap.get(name);
}
}

3.3.7 性能分析

时间复杂度
  • operation():O(n),n 是组件树中的节点数量
  • add():O(1),添加到列表末尾
  • remove():O(n),需要遍历列表找到要移除的组件
  • getChild():O(1),直接访问列表元素
  • isComposite():O(1),直接返回布尔值
空间复杂度
  • Component:O(1),每个组件存储基本信息
  • Leaf:O(1),不存储子组件
  • Composite:O(n),n 是子组件数量
  • 整体:O(n),n 是组件树中的节点数量
性能优化策略
  1. 使用更高效的数据结构

    • 对于频繁查找的场景,使用哈希表存储子组件
    • 对于需要排序的场景,使用平衡二叉搜索树
  2. 懒加载

    • 延迟初始化子组件,减少启动时间
    • 只在需要时加载子组件
  3. 缓存

    • 缓存操作结果,避免重复计算
    • 缓存常用的子组件引用
  4. 批处理

    • 批量添加或删除子组件,减少操作次数
    • 使用事务方式处理多个组件操作
  5. 并行处理

    • 对于大型组件树,使用并行处理提高操作速度
    • 适用于操作之间无依赖关系的场景

3.3.8 优缺点

优点:

  • 统一接口:客户端可以统一处理单个对象和组合对象
  • 灵活性:容易添加新的组件类型,扩展树形结构
  • 可维护性:简化客户端代码,减少重复代码
  • 扩展性:可以形成复杂的树形结构,支持任意深度的组合
  • 符合开闭原则:对扩展开放,对修改关闭

缺点:

  • 复杂性:可能会使设计变得过于一般化,某些操作可能不适合叶节点
  • 性能问题:处理大型树形结构时可能会导致性能问题
  • 内存开销:每个组件都需要存储额外的信息,如父引用
  • 错误处理:需要仔细处理叶节点的不支持操作

3.3.9 应用场景

适合使用组合模式的场景:

  1. 文件系统

    • 目录和文件的层次结构
    • 统一处理文件和目录操作
  2. 图形界面

    • UI 组件的层次结构
    • 如窗口、面板、按钮等
  3. 组织结构

    • 公司部门和员工的层次结构
    • 统一处理部门和员工操作
  4. 菜单系统

    • 菜单和子菜单的层次结构
    • 统一处理菜单项和子菜单
  5. 配置系统

    • 配置项的层次结构
    • 统一处理简单配置和配置组
  6. XML/JSON 解析

    • 树形数据结构的处理
    • 统一处理元素和元素组

实际应用案例:

1. 文件系统

场景:实现文件系统的目录和文件操作,统一处理文件和目录。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// 组件接口
public abstract class FileSystemComponent {
protected String name;
protected long size;
protected FileSystemComponent parent;

public FileSystemComponent(String name) {
this.name = name;
}

public abstract void operation();
public abstract long getSize();
public abstract void display(int depth);

public void add(FileSystemComponent component) {
throw new UnsupportedOperationException();
}

public void remove(FileSystemComponent component) {
throw new UnsupportedOperationException();
}

public FileSystemComponent getChild(int index) {
throw new UnsupportedOperationException();
}

public FileSystemComponent getParent() {
return parent;
}

public void setParent(FileSystemComponent parent) {
this.parent = parent;
}

public boolean isComposite() {
return false;
}

public String getName() {
return name;
}
}

// 叶节点 - 文件
public class File extends FileSystemComponent {
private String content;

public File(String name, String content) {
super(name);
this.content = content;
this.size = content.length();
}

@Override
public void operation() {
System.out.println("Reading file: " + name);
System.out.println("Content: " + content);
}

@Override
public long getSize() {
return size;
}

@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "File: " + name + " (" + size + " bytes)");
}
}

// 复合节点 - 目录
public class Directory extends FileSystemComponent {
private List<FileSystemComponent> children = new ArrayList<>();

public Directory(String name) {
super(name);
}

@Override
public void operation() {
System.out.println("Listing directory: " + name);
for (FileSystemComponent child : children) {
child.operation();
}
}

@Override
public long getSize() {
long totalSize = 0;
for (FileSystemComponent child : children) {
totalSize += child.getSize();
}
return totalSize;
}

@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "Directory: " + name + " (" + getSize() + " bytes)");
for (FileSystemComponent child : children) {
child.display(depth + 1);
}
}

@Override
public void add(FileSystemComponent component) {
children.add(component);
component.setParent(this);
}

@Override
public void remove(FileSystemComponent component) {
children.remove(component);
component.setParent(null);
}

@Override
public FileSystemComponent getChild(int index) {
return children.get(index);
}

@Override
public boolean isComposite() {
return true;
}

public int getChildCount() {
return children.size();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// 创建文件系统结构
Directory root = new Directory("/";
Directory home = new Directory("home");
Directory user = new Directory("user");
Directory docs = new Directory("docs");
Directory pics = new Directory("pics");

File file1 = new File("README.md", "# Project README");
File file2 = new File("main.java", "public class Main { ... }");
File file3 = new File("photo.jpg", "[Binary data]");

// 构建目录结构
root.add(home);
home.add(user);
user.add(docs);
user.add(pics);
docs.add(file1);
docs.add(file2);
pics.add(file3);

// 显示文件系统结构
System.out.println("=== File System Structure ===");
root.display(0);

// 执行操作
System.out.println("\n=== Executing Operations ===");
root.operation();

// 测试大小计算
System.out.println("\n=== Size Calculation ===");
System.out.println("Root directory size: " + root.getSize() + " bytes");
System.out.println("User directory size: " + user.getSize() + " bytes");
System.out.println("Docs directory size: " + docs.getSize() + " bytes");

// 测试删除操作
System.out.println("\n=== After Deleting File ===");
docs.remove(file1);
root.display(0);
System.out.println("Docs directory size: " + docs.getSize() + " bytes");
}
}
2. GUI 组件系统

场景:实现图形界面的组件层次结构,统一处理简单组件和复合组件。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <iostream>
#include <vector>
#include <string>

// 组件接口
class UIComponent {
protected:
std::string name;
int x, y, width, height;
UIComponent* parent;
public:
UIComponent(const std::string& name, int x, int y, int width, int height)
: name(name), x(x), y(y), width(width), height(height), parent(nullptr) {
}

virtual ~UIComponent() {
}

virtual void draw() = 0;
virtual void handleEvent(const std::string& event) = 0;

virtual void add(UIComponent* component) {
throw std::runtime_error("Unsupported operation");
}

virtual void remove(UIComponent* component) {
throw std::runtime_error("Unsupported operation");
}

virtual UIComponent* getChild(int index) {
throw std::runtime_error("Unsupported operation");
}

virtual UIComponent* getParent() {
return parent;
}

virtual void setParent(UIComponent* parent) {
this->parent = parent;
}

virtual bool isComposite() {
return false;
}

const std::string& getName() {
return name;
}

void setPosition(int x, int y) {
this->x = x;
this->y = y;
}

void setSize(int width, int height) {
this->width = width;
this->height = height;
}
};

// 叶节点 - 按钮
class Button : public UIComponent {
private:
std::string label;
public:
Button(const std::string& name, int x, int y, int width, int height, const std::string& label)
: UIComponent(name, x, y, width, height), label(label) {
}

void draw() override {
std::cout << "Drawing Button: " << name << " at (" << x << ", " << y << ") with label: " << label << std::endl;
}

void handleEvent(const std::string& event) override {
if (event == "click") {
std::cout << "Button " << name << " clicked!" << std::endl;
}
}
};

// 叶节点 - 文本框
class TextBox : public UIComponent {
private:
std::string text;
public:
TextBox(const std::string& name, int x, int y, int width, int height, const std::string& text)
: UIComponent(name, x, y, width, height), text(text) {
}

void draw() override {
std::cout << "Drawing TextBox: " << name << " at (" << x << ", " << y << ") with text: " << text << std::endl;
}

void handleEvent(const std::string& event) override {
if (event == "input") {
std::cout << "TextBox " << name << " input received!" << std::endl;
}
}
};

// 复合节点 - 面板
class Panel : public UIComponent {
private:
std::vector<UIComponent*> children;
std::string background;
public:
Panel(const std::string& name, int x, int y, int width, int height, const std::string& background)
: UIComponent(name, x, y, width, height), background(background) {
}

~Panel() {
for (UIComponent* child : children) {
delete child;
}
}

void draw() override {
std::cout << "Drawing Panel: " << name << " at (" << x << ", " << y << ") with background: " << background << std::endl;
for (UIComponent* child : children) {
child->draw();
}
}

void handleEvent(const std::string& event) override {
std::cout << "Panel " << name << " handling event: " << event << std::endl;
for (UIComponent* child : children) {
child->handleEvent(event);
}
}

void add(UIComponent* component) override {
children.push_back(component);
component->setParent(this);
}

void remove(UIComponent* component) override {
auto it = std::find(children.begin(), children.end(), component);
if (it != children.end()) {
(*it)->setParent(nullptr);
children.erase(it);
}
}

UIComponent* getChild(int index) override {
if (index >= 0 && index < children.size()) {
return children[index];
}
return nullptr;
}

bool isComposite() override {
return true;
}

int getChildCount() {
return children.size();
}
};

// 客户端使用
int main() {
// 创建 UI 组件
Panel* mainWindow = new Panel("MainWindow", 0, 0, 800, 600, "white");
Panel* loginPanel = new Panel("LoginPanel", 100, 100, 400, 300, "lightgray");
TextBox* usernameBox = new TextBox("UsernameBox", 50, 50, 300, 30, "");
TextBox* passwordBox = new TextBox("PasswordBox", 50, 100, 300, 30, "");
Button* loginButton = new Button("LoginButton", 50, 150, 100, 30, "Login");
Button* cancelButton = new Button("CancelButton", 200, 150, 100, 30, "Cancel");

// 构建 UI 层次结构
mainWindow->add(loginPanel);
loginPanel->add(usernameBox);
loginPanel->add(passwordBox);
loginPanel->add(loginButton);
loginPanel->add(cancelButton);

// 绘制 UI
std::cout << "=== Drawing UI ===" << std::endl;
mainWindow->draw();

// 处理事件
std::cout << "\n=== Handling Events ===" << std::endl;
mainWindow->handleEvent("click");
mainWindow->handleEvent("input");

// 测试子组件操作
std::cout << "\n=== Component Operations ===" << std::endl;
std::cout << "MainWindow child count: " << mainWindow->getChildCount() << std::endl;
std::cout << "LoginPanel child count: " << loginPanel->getChildCount() << std::endl;

// 测试删除操作
std::cout << "\n=== After Removing Cancel Button ===" << std::endl;
loginPanel->remove(cancelButton);
std::cout << "LoginPanel child count: " << loginPanel->getChildCount() << std::endl;
mainWindow->draw();

delete mainWindow;
return 0;
}
3. 菜单系统

场景:实现菜单和子菜单的层次结构,统一处理菜单项和子菜单。

实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// 组件接口
public abstract class MenuComponent {
protected String name;
protected String url;
protected MenuComponent parent;

public MenuComponent(String name) {
this.name = name;
}

public abstract void operation();
public abstract void display(int depth);

public void add(MenuComponent component) {
throw new UnsupportedOperationException();
}

public void remove(MenuComponent component) {
throw new UnsupportedOperationException();
}

public MenuComponent getChild(int index) {
throw new UnsupportedOperationException();
}

public MenuComponent getParent() {
return parent;
}

public void setParent(MenuComponent parent) {
this.parent = parent;
}

public boolean isComposite() {
return false;
}

public String getName() {
return name;
}

public void setUrl(String url) {
this.url = url;
}

public String getUrl() {
return url;
}
}

// 叶节点 - 菜单项
public class MenuItem extends MenuComponent {
public MenuItem(String name, String url) {
super(name);
this.url = url;
}

@Override
public void operation() {
System.out.println("Navigating to: " + url);
}

@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "MenuItem: " + name + " (" + url + ")");
}
}

// 复合节点 - 菜单
public class Menu extends MenuComponent {
private List<MenuComponent> children = new ArrayList<>();

public Menu(String name) {
super(name);
}

@Override
public void operation() {
System.out.println("Opening menu: " + name);
for (MenuComponent child : children) {
child.operation();
}
}

@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "Menu: " + name);
for (MenuComponent child : children) {
child.display(depth + 1);
}
}

@Override
public void add(MenuComponent component) {
children.add(component);
component.setParent(this);
}

@Override
public void remove(MenuComponent component) {
children.remove(component);
component.setParent(null);
}

@Override
public MenuComponent getChild(int index) {
return children.get(index);
}

@Override
public boolean isComposite() {
return true;
}

public int getChildCount() {
return children.size();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// 创建菜单结构
Menu mainMenu = new Menu("Main Menu");
Menu fileMenu = new Menu("File");
Menu editMenu = new Menu("Edit");
Menu viewMenu = new Menu("View");
Menu helpMenu = new Menu("Help");

MenuItem newItem = new MenuItem("New", "/new");
MenuItem openItem = new MenuItem("Open", "/open");
MenuItem saveItem = new MenuItem("Save", "/save");
MenuItem exitItem = new MenuItem("Exit", "/exit");

MenuItem cutItem = new MenuItem("Cut", "/cut");
MenuItem copyItem = new MenuItem("Copy", "/copy");
MenuItem pasteItem = new MenuItem("Paste", "/paste");

MenuItem zoomMenu = new Menu("Zoom");
MenuItem zoomInItem = new MenuItem("Zoom In", "/zoom-in");
MenuItem zoomOutItem = new MenuItem("Zoom Out", "/zoom-out");
MenuItem resetZoomItem = new MenuItem("Reset Zoom", "/reset-zoom");

MenuItem aboutItem = new MenuItem("About", "/about");

// 构建菜单层次结构
mainMenu.add(fileMenu);
mainMenu.add(editMenu);
mainMenu.add(viewMenu);
mainMenu.add(helpMenu);

fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.add(exitItem);

editMenu.add(cutItem);
editMenu.add(copyItem);
editMenu.add(pasteItem);

viewMenu.add(zoomMenu);
zoomMenu.add(zoomInItem);
zoomMenu.add(zoomOutItem);
zoomMenu.add(resetZoomItem);

helpMenu.add(aboutItem);

// 显示菜单结构
System.out.println("=== Menu Structure ===");
mainMenu.display(0);

// 执行操作
System.out.println("\n=== Executing Operations ===");
mainMenu.operation();

// 测试子菜单操作
System.out.println("\n=== Menu Operations ===");
System.out.println("Main menu child count: " + mainMenu.getChildCount());
System.out.println("File menu child count: " + fileMenu.getChildCount());
System.out.println("Zoom menu child count: " + zoomMenu.getChildCount());

// 测试删除操作
System.out.println("\n=== After Removing Save Item ===");
fileMenu.remove(saveItem);
fileMenu.display(1);
System.out.println("File menu child count: " + fileMenu.getChildCount());
}
}

3.3.10 最佳实践

1. 组合策略选择

安全组合 vs 透明组合

特性安全组合透明组合
类型安全
接口一致性
客户端复杂度
适用场景严格类型检查统一接口处理
2. 组合实现技巧

Java 实现技巧

  1. 使用泛型

    • 实现类型安全的组合模式
    • 减少类型转换错误
  2. 使用枚举

    • 表示组件类型,提高代码可读性
    • 便于类型判断和处理
  3. 异常处理

    • 在叶节点的不支持操作中抛出明确的异常
    • 提供详细的错误信息,便于调试

C++ 实现技巧

  1. 智能指针管理

    • 使用 std::unique_ptrstd::shared_ptr 管理组件生命周期
    • 避免内存泄漏和悬垂指针
  2. 模板特化

    • 使用模板实现通用的组合逻辑
    • 为特定类型提供特化实现
  3. RAII 原则

    • 遵循 RAII 原则,确保资源正确释放
    • 减少资源管理错误
3. 模式组合策略

与访问者模式结合

  • 使用访问者模式遍历组件树,执行特定操作
  • 适用于需要对组件树进行复杂操作的场景

与迭代器模式结合

  • 为组件树提供统一的遍历接口
  • 支持不同的遍历方式,如深度优先、广度优先

与命令模式结合

  • 将组件操作封装为命令对象
  • 支持撤销/重做操作

与装饰器模式结合

  • 为组件添加额外的功能,如缓存、日志等
  • 保持组件接口的一致性
4. 代码设计最佳实践

命名规范

  • 组件类名:ComponentLeafComposite 或具体业务名称
  • 方法名:使用语义明确的动词,如 addremovegetChild
  • 变量名:使用描述性名称,避免缩写

包结构组织

  • 将组合模式相关类放在同一包或模块中
  • 按功能划分:核心组件、具体实现、工具类
  • 保持包结构清晰,便于维护

文档和注释

  • 为组合模式添加详细的注释,说明组件层次结构
  • 记录组件的职责和使用方法
  • 说明组合模式的适用场景和限制

错误处理

  • 组件应优雅处理运行时异常
  • 提供一致的错误处理机制
  • 实现容错机制,确保系统稳定性
5. 测试策略

单元测试

  • 测试组件的基本操作
  • 验证组合操作的正确性
  • 测试边界情况和特殊输入

集成测试

  • 测试组件树的构建和操作
  • 验证组合模式在实际场景中的表现
  • 测试不同配置下的组合效果

性能测试

  • 测量大型组件树的操作性能
  • 评估组合模式对系统整体性能的影响
  • 优化组合操作,减少性能损失

边界测试

  • 测试空组件树的处理
  • 验证组件树的最大深度
  • 测试并发环境下的组件操作

3.3.11 与其他模式的关系

1. 组合模式 vs 迭代器模式

核心区别

  • 目的:组合模式用于表示树形结构,迭代器模式用于遍历集合
  • 结构:组合模式关注组件的层次结构,迭代器模式关注遍历算法
  • 关系:组合模式是迭代器模式的应用场景之一

适用场景对比

  • 组合模式:需要表示「部分-整体」的层次结构
  • 迭代器模式:需要遍历集合,而不暴露其内部结构

组合使用

  • 组合模式可以使用迭代器模式来遍历组件树
  • 适用于需要多种遍历方式的场景
2. 组合模式 vs 访问者模式

核心区别

  • 目的:组合模式用于表示树形结构,访问者模式用于分离算法和数据结构
  • 结构:组合模式关注组件的层次结构,访问者模式关注操作的分离
  • 关系:访问者模式可以遍历组合模式的组件树

适用场景对比

  • 组合模式:需要表示「部分-整体」的层次结构
  • 访问者模式:需要对组件执行多种不相关的操作

组合使用

  • 组合模式可以使用访问者模式来执行复杂操作
  • 适用于需要为组件树添加新操作而不修改组件类的场景
3. 组合模式 vs 装饰器模式

核心区别

  • 目的:组合模式用于表示树形结构,装饰器模式用于动态添加功能
  • 结构:组合模式关注组件的层次结构,装饰器模式关注功能的增强
  • 关系:组合模式的组件可以被装饰器模式装饰

适用场景对比

  • 组合模式:需要表示「部分-整体」的层次结构
  • 装饰器模式:需要动态添加功能,不改变接口

组合使用

  • 组合模式的组件可以使用装饰器模式来增强功能
  • 适用于需要为组件添加额外功能的场景
4. 组合模式 vs 享元模式

核心区别

  • 目的:组合模式用于表示树形结构,享元模式用于共享对象
  • 结构:组合模式关注组件的层次结构,享元模式关注对象的共享
  • 关系:享元模式可以优化组合模式的内存使用

适用场景对比

  • 组合模式:需要表示「部分-整体」的层次结构
  • 享元模式:需要减少对象创建,节省内存

组合使用

  • 组合模式可以使用享元模式来共享叶节点
  • 适用于组件树中存在大量重复叶节点的场景
5. 模式选择指南

何时选择组合模式

  • 需要表示「部分-整体」的层次结构
  • 需要客户端统一处理单个对象和组合对象
  • 需要动态地添加或删除组件
  • 需要构建复杂的树形结构

何时选择其他模式

  • 迭代器模式:需要遍历集合,而不暴露其内部结构
  • 访问者模式:需要对组件执行多种不相关的操作
  • 装饰器模式:需要动态添加功能,不改变接口
  • 享元模式:需要减少对象创建,节省内存

模式组合建议

  • 组合 + 迭代器:遍历组件树
  • 组合 + 访问者:执行复杂操作
  • 组合 + 装饰器:增强组件功能
  • 组合 + 享元:优化内存使用

实际应用中的决策流程

  1. 分析系统中是否存在「部分-整体」的层次结构
  2. 评估客户端代码是否需要统一处理单个对象和组合对象
  3. 选择合适的组合策略(安全组合或透明组合)
  4. 设计组件接口和实现类
  5. 实现具体的组件和组合逻辑
  6. 测试组合模式的功能和性能
  7. 监控组合模式在生产环境中的表现

3.4 装饰器模式(Decorator)

3.4.1 意图

动态地给一个对象添加一些额外的职责。装饰器模式提供了一种比继承更灵活的方式来扩展对象的功能。

3.4.2 动机

当需要给一个对象添加额外的功能,而又不希望通过继承来实现时,可以使用装饰器模式。

3.4.3 结构

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
+----------------+
| Component |
+----------------+
| + operation() |
+----------------+
^
|
+----------------+ +----------------+
| ConcreteComponent| | Decorator |
+----------------+ +----------------+
| + operation() | | - component: |
+----------------+ | Component |
| + operation() |
+----------------+
^
|
+----------------+
| ConcreteDecoratorA|
+----------------+
| + operation() |
| + addedBehavior()|
+----------------+
^
|
+----------------+
| ConcreteDecoratorB|
+----------------+
| + operation() |
| + addedBehavior()|
+----------------+

3.4.4 参与者

  • Component:定义组件的接口
  • ConcreteComponent:实现组件接口的具体类
  • Decorator:装饰器的抽象类,包含一个对 Component 的引用
  • ConcreteDecorator:具体的装饰器,添加额外的功能

3.4.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// 组件接口
public interface Component {
void operation();
}

// 具体组件
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation");
}
}

// 装饰器抽象类
public abstract class Decorator implements Component {
protected Component component;

public Decorator(Component component) {
this.component = component;
}

@Override
public void operation() {
component.operation();
}
}

// 具体装饰器A
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}

@Override
public void operation() {
super.operation();
addedBehavior();
}

private void addedBehavior() {
System.out.println("ConcreteDecoratorA added behavior");
}
}

// 具体装饰器B
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}

@Override
public void operation() {
super.operation();
addedBehavior();
}

private void addedBehavior() {
System.out.println("ConcreteDecoratorB added behavior");
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
System.out.println("原始组件:");
component.operation();

System.out.println("\n装饰器A:");
Component decoratorA = new ConcreteDecoratorA(component);
decoratorA.operation();

System.out.println("\n装饰器B:");
Component decoratorB = new ConcreteDecoratorB(component);
decoratorB.operation();

System.out.println("\n装饰器A + B:");
Component decoratorAB = new ConcreteDecoratorB(new ConcreteDecoratorA(component));
decoratorAB.operation();
}
}

3.4.6 优缺点

优点:

  • 动态地添加额外的功能,不需要修改原有代码
  • 可以组合多个装饰器,实现功能的叠加
  • 比继承更加灵活,避免了类爆炸

缺点:

  • 增加了代码复杂度
  • 可能会导致系统中出现大量的小对象
  • 装饰器的顺序很重要,可能会影响最终的行为

3.4.7 应用场景

  • 当需要动态地给一个对象添加额外的功能时
  • 当需要避免使用继承来扩展对象功能时
  • 当需要组合多个功能时

3.5 外观模式(Facade)

3.5.1 意图

为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,使得子系统更加容易使用。

3.5.2 动机

当一个系统变得复杂时,使用外观模式可以为客户端提供一个简单的接口,隐藏系统的复杂性。

3.5.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Facade |
+----------------+
| - subsystem1: |
| Subsystem1 |
| - subsystem2: |
| Subsystem2 |
| - subsystem3: |
| Subsystem3 |
| + methodA() |
| + methodB() |
+----------------+
|
|
+----------------+ +----------------+ +----------------+
| Subsystem1 | | Subsystem2 | | Subsystem3 |
+----------------+ +----------------+ +----------------+
| + operation1() | | + operation2() | | + operation3() |
+----------------+ +----------------+ +----------------+

3.5.4 参与者

  • Facade:提供统一的接口,隐藏子系统的复杂性
  • Subsystem:子系统的各个组件
  • Client:使用 Facade 接口

3.5.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 子系统1
public class Subsystem1 {
public void operation1() {
System.out.println("Subsystem1 operation1");
}
}

// 子系统2
public class Subsystem2 {
public void operation2() {
System.out.println("Subsystem2 operation2");
}
}

// 子系统3
public class Subsystem3 {
public void operation3() {
System.out.println("Subsystem3 operation3");
}
}

// 外观类
public class Facade {
private Subsystem1 subsystem1;
private Subsystem2 subsystem2;
private Subsystem3 subsystem3;

public Facade() {
subsystem1 = new Subsystem1();
subsystem2 = new Subsystem2();
subsystem3 = new Subsystem3();
}

public void methodA() {
System.out.println("Facade methodA:");
subsystem1.operation1();
subsystem2.operation2();
}

public void methodB() {
System.out.println("Facade methodB:");
subsystem2.operation2();
subsystem3.operation3();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.methodA();
System.out.println();
facade.methodB();
}
}

3.5.6 优缺点

优点:

  • 简化了客户端的使用,提供了一个统一的接口
  • 降低了客户端与子系统之间的耦合度
  • 提高了系统的可维护性

缺点:

  • 可能会导致外观类变得过于复杂,承担过多的责任
  • 可能会限制客户端对子系统的直接访问

3.5.7 应用场景

  • 当需要为一个复杂的子系统提供一个简单的接口时
  • 当需要减少客户端与子系统之间的耦合度时
  • 当需要统一多个子系统的接口时

3.6 享元模式(Flyweight)

3.6.1 意图

运用共享技术有效地支持大量细粒度的对象。

3.6.2 动机

当需要创建大量相似的对象时,使用享元模式可以减少对象的数量,节省内存空间。

3.6.3 结构

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
+----------------+
| FlyweightFactory|
+----------------+
| - flyweights: |
| Map |
| + getFlyweight():|
| Flyweight |
+----------------+
|
|
+----------------+
| Flyweight |
+----------------+
| + operation() |
+----------------+
^
|
+----------------+ +----------------+
| ConcreteFlyweight| | UnsharedConcreteFlyweight|
| | | |
+----------------+ +----------------+
| + operation() | | + operation() |
+----------------+ +----------------+

+----------------+
| Client |
+----------------+
| + operation() |
+----------------+

3.6.4 参与者

  • Flyweight:定义享元对象的接口
  • ConcreteFlyweight:实现享元对象的接口,存储内部状态
  • UnsharedConcreteFlyweight:不需要共享的享元对象
  • FlyweightFactory:创建和管理享元对象,确保合理共享
  • Client:使用享元对象

3.6.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 享元接口
public interface Flyweight {
void operation(String extrinsicState);
}

// 具体享元
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState;

public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}

@Override
public void operation(String extrinsicState) {
System.out.println("ConcreteFlyweight: " + intrinsicState + " with " + extrinsicState);
}
}

// 享元工厂
public class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();

public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}

public int getFlyweightCount() {
return flyweights.size();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();

Flyweight flyweight1 = factory.getFlyweight("A");
flyweight1.operation("外部状态1");

Flyweight flyweight2 = factory.getFlyweight("B");
flyweight2.operation("外部状态2");

Flyweight flyweight3 = factory.getFlyweight("A");
flyweight3.operation("外部状态3");

System.out.println("享元对象数量:" + factory.getFlyweightCount());
}
}

3.6.6 优缺点

优点:

  • 减少对象数量,节省内存空间
  • 提高系统性能
  • 可以共享相似对象

缺点:

  • 增加了系统复杂度
  • 需要分离内部状态和外部状态
  • 可能会影响系统的灵活性

3.6.7 应用场景

  • 当需要创建大量相似对象时
  • 当对象的大部分状态可以外部化时
  • 当需要节省内存空间时

3.7 代理模式(Proxy)

3.7.1 意图

为其他对象提供一种代理以控制对这个对象的访问。

3.7.2 动机

当需要在访问一个对象时添加额外的功能,或者需要控制对对象的访问时,可以使用代理模式。

3.7.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Proxy |
+----------------+
| - realSubject: |
| Subject |
| + operation() |
+----------------+
^
|
+----------------+
| Subject |
+----------------+
| + operation() |
+----------------+
^
|
+----------------+
| RealSubject |
+----------------+
| + operation() |
+----------------+

3.7.4 参与者

  • Subject:定义代理和真实对象的共同接口
  • RealSubject:真实对象,代理所代表的对象
  • Proxy:代理对象,控制对真实对象的访问
  • Client:使用代理对象

3.7.5 实现

Java 实现:

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
38
39
40
// 主题接口
public interface Subject {
void operation();
}

// 真实主题
public class RealSubject implements Subject {
@Override
public void operation() {
System.out.println("RealSubject operation");
}
}

// 代理
public class Proxy implements Subject {
private RealSubject realSubject;

@Override
public void operation() {
// 前置处理
System.out.println("Proxy before operation");

// 调用真实对象
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.operation();

// 后置处理
System.out.println("Proxy after operation");
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.operation();
}
}

动态代理实现:

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
// 动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
private Object target;

public DynamicProxyHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置处理
System.out.println("DynamicProxy before operation");

// 调用目标方法
Object result = method.invoke(target, args);

// 后置处理
System.out.println("DynamicProxy after operation");

return result;
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class[]{Subject.class},
new DynamicProxyHandler(realSubject)
);
proxy.operation();
}
}

3.7.6 优缺点

优点:

  • 可以在访问对象时添加额外的功能
  • 可以控制对对象的访问
  • 可以实现延迟加载

缺点:

  • 增加了代码复杂度
  • 可能会影响系统性能

3.7.7 应用场景

  • 当需要在访问对象时添加额外的功能时
  • 当需要控制对对象的访问时
  • 当需要实现延迟加载时
  • 当需要远程访问对象时

第四部分:行为型模式

4.1 命令模式(Command)

4.1.1 意图

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

4.1.2 动机

当需要将请求的发送者和接收者解耦时,可以使用命令模式。

4.1.3 结构

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
38
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Invoker |
+----------------+
| - command: |
| Command |
| + setCommand() |
| + execute() |
+----------------+
|
|
+----------------+
| Command |
+----------------+
| + execute() |
+----------------+
^
|
+----------------+
| ConcreteCommand|
+----------------+
| - receiver: |
| Receiver |
| + execute() |
+----------------+
|
|
+----------------+
| Receiver |
+----------------+
| + action() |
+----------------+

4.1.4 参与者

  • Command:定义命令的接口
  • ConcreteCommand:实现命令接口,包含接收者
  • Invoker:调用者,执行命令
  • Receiver:接收者,执行实际的操作
  • Client:创建命令对象并设置接收者

4.1.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
// 命令接口
public interface Command {
void execute();
}

// 接收者
public class Receiver {
public void action() {
System.out.println("Receiver action");
}
}

// 具体命令
public class ConcreteCommand implements Command {
private Receiver receiver;

public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
receiver.action();
}
}

// 调用者
public class Invoker {
private Command command;

public void setCommand(Command command) {
this.command = command;
}

public void executeCommand() {
command.execute();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
}

撤销操作实现:

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
38
39
40
// 命令接口
public interface Command {
void execute();
void undo();
}

// 具体命令
public class ConcreteCommand implements Command {
private Receiver receiver;
private String previousState;

public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
// 保存当前状态
previousState = receiver.getState();
receiver.action();
}

@Override
public void undo() {
// 恢复之前的状态
receiver.setState(previousState);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
invoker.undoCommand();
}
}

4.1.6 优缺点

优点:

  • 解耦请求发送者和接收者
  • 容易添加新的命令
  • 支持命令的撤销和重做
  • 可以将多个命令组合成复合命令

缺点:

  • 增加了代码复杂度
  • 需要创建更多的类

4.1.7 应用场景

  • 当需要将请求的发送者和接收者解耦时
  • 当需要支持命令的撤销和重做时
  • 当需要将多个命令组合成复合命令时
  • 当需要记录请求日志时

4.2 迭代器模式(Iterator)

4.2.1 意图

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

4.2.2 动机

当需要遍历一个聚合对象中的元素,而又不希望暴露其内部结构时,可以使用迭代器模式。

4.2.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+ +----------------+
| Aggregate | | Iterator |
+----------------+ +----------------+
| + createIterator():| | + hasNext(): |
| Iterator | | boolean |
+----------------+ | + next(): |
^ | Object |
| +----------------+
+----------------+ ^
| ConcreteAggregate| |
+----------------+ +----------------+
| + createIterator():| | ConcreteIterator|
| Iterator | +----------------+
| - items: | | - aggregate: |
| List<Object> | | Aggregate |
+----------------+ | - index: |
| int |
| + hasNext(): |
| boolean |
| + next(): |
| Object |
+----------------+

4.2.4 参与者

  • Iterator:定义迭代器的接口
  • ConcreteIterator:实现迭代器接口
  • Aggregate:定义聚合对象的接口
  • ConcreteAggregate:实现聚合对象接口
  • Client:使用迭代器遍历聚合对象

4.2.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 迭代器接口
public interface Iterator {
boolean hasNext();
Object next();
}

// 聚合接口
public interface Aggregate {
Iterator createIterator();
}

// 具体迭代器
public class ConcreteIterator implements Iterator {
private ConcreteAggregate aggregate;
private int index;

public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
this.index = 0;
}

@Override
public boolean hasNext() {
return index < aggregate.getSize();
}

@Override
public Object next() {
if (hasNext()) {
return aggregate.getItem(index++);
}
return null;
}
}

// 具体聚合
public class ConcreteAggregate implements Aggregate {
private List<Object> items = new ArrayList<>();

public void addItem(Object item) {
items.add(item);
}

public Object getItem(int index) {
return items.get(index);
}

public int getSize() {
return items.size();
}

@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate();
aggregate.addItem("Item 1");
aggregate.addItem("Item 2");
aggregate.addItem("Item 3");

Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {
Object item = iterator.next();
System.out.println(item);
}
}
}

Java 内置迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 客户端使用
public class Client {
public static void main(String[] args) {
List<String> items = new ArrayList<>();
items.add("Item 1");
items.add("Item 2");
items.add("Item 3");

// 使用内置迭代器
for (String item : items) {
System.out.println(item);
}

// 或者使用显式迭代器
Iterator<String> iterator = items.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
}
}

4.2.6 优缺点

优点:

  • 解耦聚合对象和遍历算法
  • 支持多种遍历方式
  • 简化聚合对象的接口
  • 符合单一职责原则

缺点:

  • 增加了代码复杂度
  • 需要创建额外的迭代器对象

4.2.7 应用场景

  • 当需要遍历一个聚合对象,而又不希望暴露其内部结构时
  • 当需要支持多种遍历方式时
  • 当需要为不同的聚合对象提供统一的遍历接口时

4.3 观察者模式(Observer)

4.3.1 意图

定义对象间的一种一对多依赖关系,使得每当一个对象状态发生变化时,其相关依赖对象都得到通知并被自动更新。

4.3.2 动机

当一个对象的状态变化需要通知其他对象,而又不希望这些对象与它紧密耦合时,可以使用观察者模式。

4.3.3 结构

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
+----------------+
| Subject |
+----------------+
| + attach(Observer)|
| + detach(Observer)|
| + notifyObservers()|
+----------------+
^
|
+----------------+
| ConcreteSubject|
+----------------+
| - state: |
| Object |
| + getState() |
| + setState() |
+----------------+
|
|
+----------------+
| Observer |
+----------------+
| + update() |
+----------------+
^
|
+----------------+
| ConcreteObserver|
+----------------+
| - subject: |
| Subject |
| - state: |
| Object |
| + update() |
+----------------+

4.3.4 参与者

  • Subject:主题接口,定义添加、删除和通知观察者的方法
  • ConcreteSubject:具体主题,实现主题接口,维护状态并通知观察者
  • Observer:观察者接口,定义更新方法
  • ConcreteObserver:具体观察者,实现观察者接口,接收通知并更新状态

4.3.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 观察者接口
public interface Observer {
void update();
}

// 主题接口
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}

// 具体主题
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
notifyObservers();
}

@Override
public void attach(Observer observer) {
observers.add(observer);
}

@Override
public void detach(Observer observer) {
observers.remove(observer);
}

@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}

// 具体观察者
public class ConcreteObserver implements Observer {
private ConcreteSubject subject;
private int state;

public ConcreteObserver(ConcreteSubject subject) {
this.subject = subject;
subject.attach(this);
}

@Override
public void update() {
state = subject.getState();
System.out.println("Observer state updated: " + state);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver(subject);
ConcreteObserver observer2 = new ConcreteObserver(subject);

subject.setState(1);
subject.setState(2);

subject.detach(observer1);
subject.setState(3);
}
}

Java 内置观察者模式:

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
38
39
40
41
42
43
44
45
46
// 主题类
public class ConcreteSubject extends Observable {
private int state;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
setChanged(); // 标记状态已改变
notifyObservers(); // 通知观察者
}
}

// 观察者类
public class ConcreteObserver implements Observer {
private int state;

@Override
public void update(Observable o, Object arg) {
if (o instanceof ConcreteSubject) {
ConcreteSubject subject = (ConcreteSubject) o;
state = subject.getState();
System.out.println("Observer state updated: " + state);
}
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver();
ConcreteObserver observer2 = new ConcreteObserver();

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.setState(1);
subject.setState(2);

subject.deleteObserver(observer1);
subject.setState(3);
}
}

4.3.6 优缺点

优点:

  • 解耦主题和观察者
  • 支持广播通信
  • 符合开闭原则
  • 可以动态添加或删除观察者

缺点:

  • 可能导致通知链过长,影响性能
  • 可能导致循环依赖
  • 观察者无法知道主题状态变化的具体原因

4.3.7 应用场景

  • 当一个对象的状态变化需要通知其他对象时
  • 当需要在运行时动态添加或删除观察者时
  • 当主题和观察者之间的耦合度需要降低时

4.4 中介者模式(Mediator)

4.4.1 意图

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

4.4.2 动机

当多个对象之间存在复杂的交互关系时,可以使用中介者模式来简化它们之间的通信。

4.4.3 结构

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
38
39
40
41
42
43
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Mediator |
+----------------+
| + sendMessage()|
| + register(Colleague)|
+----------------+
^
|
+----------------+
| ConcreteMediator|
+----------------+
| - colleagues: |
| List<Colleague>|
| + sendMessage()|
| + register(Colleague)|
+----------------+
|
|
+----------------+
| Colleague |
+----------------+
| - mediator: |
| Mediator |
| + sendMessage()|
| + receiveMessage()|
+----------------+
^
|
+----------------+ +----------------+
| ConcreteColleague1| | ConcreteColleague2|
+----------------+ +----------------+
| + sendMessage()|
| + receiveMessage()|
+----------------+ +----------------+
| + receiveMessage()|
+----------------+

4.4.4 参与者

  • Mediator:中介者接口,定义通信方法
  • ConcreteMediator:具体中介者,实现中介者接口,协调同事对象之间的通信
  • Colleague:同事接口,定义与中介者通信的方法
  • ConcreteColleague:具体同事,实现同事接口,通过中介者与其他同事通信
  • Client:使用中介者和同事对象

4.4.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 中介者接口
public interface Mediator {
void sendMessage(String message, Colleague colleague);
void register(Colleague colleague);
}

// 同事接口
public abstract class Colleague {
protected Mediator mediator;

public Colleague(Mediator mediator) {
this.mediator = mediator;
mediator.register(this);
}

public abstract void sendMessage(String message);
public abstract void receiveMessage(String message);
}

// 具体中介者
public class ConcreteMediator implements Mediator {
private List<Colleague> colleagues = new ArrayList<>();

@Override
public void register(Colleague colleague) {
colleagues.add(colleague);
}

@Override
public void sendMessage(String message, Colleague colleague) {
for (Colleague c : colleagues) {
if (c != colleague) {
c.receiveMessage(message);
}
}
}
}

// 具体同事1
public class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}

@Override
public void sendMessage(String message) {
System.out.println("Colleague1 sends: " + message);
mediator.sendMessage(message, this);
}

@Override
public void receiveMessage(String message) {
System.out.println("Colleague1 receives: " + message);
}
}

// 具体同事2
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}

@Override
public void sendMessage(String message) {
System.out.println("Colleague2 sends: " + message);
mediator.sendMessage(message, this);
}

@Override
public void receiveMessage(String message) {
System.out.println("Colleague2 receives: " + message);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
Colleague colleague1 = new ConcreteColleague1(mediator);
Colleague colleague2 = new ConcreteColleague2(mediator);

colleague1.sendMessage("Hello from Colleague1");
colleague2.sendMessage("Hello from Colleague2");
}
}

4.4.6 优缺点

优点:

  • 减少对象之间的直接耦合
  • 集中管理对象之间的交互
  • 简化对象的设计
  • 提高系统的可维护性

缺点:

  • 中介者可能会变得过于复杂
  • 可能会成为系统的瓶颈
  • 可能会导致系统的可扩展性降低

4.4.7 应用场景

  • 当多个对象之间存在复杂的交互关系时
  • 当需要减少对象之间的直接耦合时
  • 当需要集中管理对象之间的交互时

4.5 备忘录模式(Memento)

4.5.1 意图

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

4.5.2 动机

当需要保存和恢复对象的状态时,可以使用备忘录模式。

4.5.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+ +----------------+
| Originator | | Caretaker |
+----------------+ +----------------+
| - state: | | - mementos: |
| String | | List<Memento>|
| + setState() | | + addMemento() |
| + getState() | | + getMemento() |
| + createMemento():|
| Memento | +----------------+
| + restoreMemento(Memento)|
+----------------+ |
| |
| |
+----------------+
| Memento |
+----------------+
| - state: |
| String |
| + getState() |
+----------------+

4.5.4 参与者

  • Originator:发起者,创建备忘录并恢复状态
  • Memento:备忘录,存储发起者的状态
  • Caretaker:管理者,保存备忘录
  • Client:使用发起者、备忘录和管理者

4.5.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// 备忘录类
public class Memento {
private final String state;

public Memento(String state) {
this.state = state;
}

public String getState() {
return state;
}
}

// 发起者类
public class Originator {
private String state;

public void setState(String state) {
this.state = state;
System.out.println("Current state: " + state);
}

public String getState() {
return state;
}

public Memento createMemento() {
return new Memento(state);
}

public void restoreMemento(Memento memento) {
state = memento.getState();
System.out.println("Restored state: " + state);
}
}

// 管理者类
public class Caretaker {
private List<Memento> mementos = new ArrayList<>();

public void addMemento(Memento memento) {
mementos.add(memento);
}

public Memento getMemento(int index) {
return mementos.get(index);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();

originator.setState("State 1");
caretaker.addMemento(originator.createMemento());

originator.setState("State 2");
caretaker.addMemento(originator.createMemento());

originator.setState("State 3");

originator.restoreMemento(caretaker.getMemento(0));
originator.restoreMemento(caretaker.getMemento(1));
}
}

4.5.6 优缺点

优点:

  • 保存和恢复对象的状态
  • 不破坏对象的封装性
  • 提供了一种后悔机制

缺点:

  • 如果对象状态很大,可能会占用较多内存
  • 如果对象状态变化频繁,可能会导致性能问题

4.5.7 应用场景

  • 当需要保存和恢复对象的状态时
  • 当需要实现撤销/重做功能时
  • 当需要监控对象状态变化时

4.6 解释器模式(Interpreter)

4.6.1 意图

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

4.6.2 动机

当需要解释和执行特定语言的句子时,可以使用解释器模式。

4.6.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Context |
+----------------+
| - variables: |
| Map<String, Integer>|
| + lookup() |
| + assign() |
+----------------+
|
|
+----------------+
| Expression |
+----------------+
| + interpret(Context)|
+----------------+
^
|
+----------------+ +----------------+
| TerminalExpression| | NonterminalExpression|
+----------------+ +----------------+
| - variable: | | - left: |
| String | | Expression |
| + interpret(Context)|
| | | - right: |
+----------------+ | Expression |
| + interpret(Context)|
+----------------+

4.6.4 参与者

  • Expression:表达式接口,定义解释方法
  • TerminalExpression:终结符表达式,实现表达式接口
  • NonterminalExpression:非终结符表达式,实现表达式接口
  • Context:上下文,存储解释器需要的信息
  • Client:使用解释器

4.6.5 实现

Java 实现(简单算术表达式解释器):

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 表达式接口
public interface Expression {
int interpret(Context context);
}

// 上下文类
public class Context {
private Map<String, Integer> variables = new HashMap<>();

public void assign(String variable, int value) {
variables.put(variable, value);
}

public int lookup(String variable) {
return variables.get(variable);
}
}

// 终结符表达式(变量)
public class VariableExpression implements Expression {
private String variable;

public VariableExpression(String variable) {
this.variable = variable;
}

@Override
public int interpret(Context context) {
return context.lookup(variable);
}
}

// 终结符表达式(常量)
public class ConstantExpression implements Expression {
private int value;

public ConstantExpression(int value) {
this.value = value;
}

@Override
public int interpret(Context context) {
return value;
}
}

// 非终结符表达式(加法)
public class AddExpression implements Expression {
private Expression left;
private Expression right;

public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}

@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}

// 非终结符表达式(减法)
public class SubtractExpression implements Expression {
private Expression left;
private Expression right;

public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}

@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
// 构建表达式:a + b - c
Context context = new Context();
context.assign("a", 10);
context.assign("b", 5);
context.assign("c", 3);

Expression expression = new SubtractExpression(
new AddExpression(
new VariableExpression("a"),
new VariableExpression("b")
),
new VariableExpression("c")
);

int result = expression.interpret(context);
System.out.println("Result: " + result); // 输出: Result: 12
}
}

4.6.6 优缺点

优点:

  • 易于扩展和修改文法
  • 可以解释复杂的语言结构
  • 符合开闭原则

缺点:

  • 对于复杂的文法,解释器可能会变得过于复杂
  • 执行效率可能较低
  • 可能会导致类的数量爆炸

4.6.7 应用场景

  • 当需要解释和执行特定语言的句子时
  • 当语言的文法比较简单时
  • 当需要扩展语言的文法时

4.7 状态模式(State)

4.7.1 意图

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

4.7.2 动机

当一个对象的行为取决于它的状态,并且它需要在运行时根据状态改变它的行为时,可以使用状态模式。

4.7.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Context |
+----------------+
| - state: |
| State |
| + setState() |
| + request() |
+----------------+
|
|
+----------------+
| State |
+----------------+
| + handle(Context)|
+----------------+
^
|
+----------------+ +----------------+
| ConcreteStateA | | ConcreteStateB |
+----------------+ +----------------+
| + handle(Context)|
| | | + handle(Context)|
+----------------+ +----------------+

4.7.4 参与者

  • Context:上下文,维护状态并委托行为给当前状态
  • State:状态接口,定义行为方法
  • ConcreteState:具体状态,实现状态接口
  • Client:使用上下文

4.7.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 状态接口
public interface State {
void handle(Context context);
}

// 上下文类
public class Context {
private State state;

public Context(State initialState) {
this.state = initialState;
}

public void setState(State state) {
this.state = state;
}

public void request() {
state.handle(this);
}
}

// 具体状态A
public class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("Handling request in State A");
// 切换到状态B
context.setState(new ConcreteStateB());
}
}

// 具体状态B
public class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("Handling request in State B");
// 切换到状态A
context.setState(new ConcreteStateA());
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());

context.request(); // 输出: Handling request in State A
context.request(); // 输出: Handling request in State B
context.request(); // 输出: Handling request in State A
context.request(); // 输出: Handling request in State B
}
}

示例:订单状态管理

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 状态接口
public interface OrderState {
void process(Order order);
void cancel(Order order);
void ship(Order order);
}

// 上下文类
public class Order {
private OrderState state;
private String orderId;

public Order(String orderId) {
this.orderId = orderId;
this.state = new PendingState();
}

public void setState(OrderState state) {
this.state = state;
}

public void process() {
state.process(this);
}

public void cancel() {
state.cancel(this);
}

public void ship() {
state.ship(this);
}

public String getOrderId() {
return orderId;
}
}

// 具体状态:待处理
public class PendingState implements OrderState {
@Override
public void process(Order order) {
System.out.println("Processing order " + order.getOrderId());
order.setState(new ProcessingState());
}

@Override
public void cancel(Order order) {
System.out.println("Cancelling order " + order.getOrderId());
order.setState(new CancelledState());
}

@Override
public void ship(Order order) {
System.out.println("Cannot ship order " + order.getOrderId() + " - it's still pending");
}
}

// 具体状态:处理中
public class ProcessingState implements OrderState {
@Override
public void process(Order order) {
System.out.println("Order " + order.getOrderId() + " is already being processed");
}

@Override
public void cancel(Order order) {
System.out.println("Cancelling order " + order.getOrderId());
order.setState(new CancelledState());
}

@Override
public void ship(Order order) {
System.out.println("Shipping order " + order.getOrderId());
order.setState(new ShippedState());
}
}

// 具体状态:已取消
public class CancelledState implements OrderState {
@Override
public void process(Order order) {
System.out.println("Cannot process order " + order.getOrderId() + " - it's cancelled");
}

@Override
public void cancel(Order order) {
System.out.println("Order " + order.getOrderId() + " is already cancelled");
}

@Override
public void ship(Order order) {
System.out.println("Cannot ship order " + order.getOrderId() + " - it's cancelled");
}
}

// 具体状态:已发货
public class ShippedState implements OrderState {
@Override
public void process(Order order) {
System.out.println("Cannot process order " + order.getOrderId() + " - it's already shipped");
}

@Override
public void cancel(Order order) {
System.out.println("Cannot cancel order " + order.getOrderId() + " - it's already shipped");
}

@Override
public void ship(Order order) {
System.out.println("Order " + order.getOrderId() + " is already shipped");
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Order order = new Order("12345");

order.process(); // 输出: Processing order 12345
order.ship(); // 输出: Shipping order 12345
order.cancel(); // 输出: Cannot cancel order 12345 - it's already shipped

Order order2 = new Order("67890");
order2.cancel(); // 输出: Cancelling order 67890
order2.process(); // 输出: Cannot process order 67890 - it's cancelled
}
}

4.7.6 优缺点

优点:

  • 将状态相关的行为集中到一个类中
  • 使状态转换更加明确
  • 避免使用大量的条件语句
  • 符合开闭原则

缺点:

  • 可能会导致类的数量增加
  • 状态转换逻辑可能会变得复杂

4.7.7 应用场景

  • 当一个对象的行为取决于它的状态时
  • 当一个对象需要在运行时根据状态改变它的行为时
  • 当需要避免使用大量的条件语句时

4.8 策略模式(Strategy)

4.8.1 意图

定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。策略模式使得算法可独立于使用它的客户而变化。

4.8.2 动机

当需要在运行时选择不同的算法时,可以使用策略模式。

4.8.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| Context |
+----------------+
| - strategy: |
| Strategy |
| + setStrategy()|
| + executeStrategy()|
+----------------+
|
|
+----------------+
| Strategy |
+----------------+
| + algorithm() |
+----------------+
^
|
+----------------+ +----------------+
| ConcreteStrategyA | | ConcreteStrategyB |
+----------------+ +----------------+
| + algorithm() |
| | | + algorithm() |
+----------------+ +----------------+

4.8.4 参与者

  • Strategy:策略接口,定义算法方法
  • ConcreteStrategy:具体策略,实现策略接口
  • Context:上下文,使用策略
  • Client:创建具体策略并设置到上下文

4.8.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
// 策略接口
public interface Strategy {
void algorithm();
}

// 具体策略A
public class ConcreteStrategyA implements Strategy {
@Override
public void algorithm() {
System.out.println("Using Strategy A");
}
}

// 具体策略B
public class ConcreteStrategyB implements Strategy {
@Override
public void algorithm() {
System.out.println("Using Strategy B");
}
}

// 上下文类
public class Context {
private Strategy strategy;

public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}

public void executeStrategy() {
strategy.algorithm();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Context context = new Context();

// 使用策略A
context.setStrategy(new ConcreteStrategyA());
context.executeStrategy(); // 输出: Using Strategy A

// 使用策略B
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy(); // 输出: Using Strategy B
}
}

示例:排序策略

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// 排序策略接口
public interface SortStrategy {
void sort(int[] array);
}

// 冒泡排序策略
public class BubbleSortStrategy implements SortStrategy {
@Override
public void sort(int[] array) {
System.out.println("Using Bubble Sort");
int n = array.length;
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (array[j] > array[j+1]) {
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
}

// 选择排序策略
public class SelectionSortStrategy implements SortStrategy {
@Override
public void sort(int[] array) {
System.out.println("Using Selection Sort");
int n = array.length;
for (int i = 0; i < n-1; i++) {
int minIndex = i;
for (int j = i+1; j < n; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
}

// 插入排序策略
public class InsertionSortStrategy implements SortStrategy {
@Override
public void sort(int[] array) {
System.out.println("Using Insertion Sort");
int n = array.length;
for (int i = 1; i < n; i++) {
int key = array[i];
int j = i-1;
while (j >= 0 && array[j] > key) {
array[j+1] = array[j];
j = j-1;
}
array[j+1] = key;
}
}
}

// 上下文类
public class SortContext {
private SortStrategy strategy;

public void setStrategy(SortStrategy strategy) {
this.strategy = strategy;
}

public void sort(int[] array) {
strategy.sort(array);
// 打印排序结果
System.out.print("Sorted array: ");
for (int num : array) {
System.out.print(num + " ");
}
System.out.println();
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
int[] array = {64, 34, 25, 12, 22, 11, 90};

SortContext context = new SortContext();

// 使用冒泡排序
context.setStrategy(new BubbleSortStrategy());
context.sort(array.clone());

// 使用选择排序
context.setStrategy(new SelectionSortStrategy());
context.sort(array.clone());

// 使用插入排序
context.setStrategy(new InsertionSortStrategy());
context.sort(array.clone());
}
}

4.8.6 优缺点

优点:

  • 可以在运行时选择不同的算法
  • 避免使用大量的条件语句
  • 符合开闭原则
  • 提高代码的可维护性

缺点:

  • 增加了类的数量
  • 客户端需要知道所有的策略

4.8.7 应用场景

  • 当需要在运行时选择不同的算法时
  • 当有多个相似的算法时
  • 当需要避免使用大量的条件语句时

4.9 模板方法模式(Template Method)

4.9.1 意图

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

4.9.2 动机

当多个类有相似的算法,但某些步骤不同时,可以使用模板方法模式。

4.9.3 结构

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
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| AbstractClass |
+----------------+
| + templateMethod()|
| + primitiveOperation1()|
| + primitiveOperation2()|
| + hook() |
+----------------+
^
|
+----------------+ +----------------+
| ConcreteClassA | | ConcreteClassB |
+----------------+ +----------------+
| + primitiveOperation1()|
| + primitiveOperation2()|
| + hook() |
+----------------+ +----------------+
| + primitiveOperation1()|
| + primitiveOperation2()|
| + hook() |
+----------------+

4.9.4 参与者

  • AbstractClass:抽象类,定义模板方法和基本操作
  • ConcreteClass:具体类,实现基本操作
  • Client:使用抽象类

4.9.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 抽象类
public abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
primitiveOperation1();
hook();
primitiveOperation2();
}

// 基本操作1
protected abstract void primitiveOperation1();

// 基本操作2
protected abstract void primitiveOperation2();

// 钩子方法
protected void hook() {
// 默认实现
}
}

// 具体类A
public class ConcreteClassA extends AbstractClass {
@Override
protected void primitiveOperation1() {
System.out.println("ConcreteClassA: primitiveOperation1");
}

@Override
protected void primitiveOperation2() {
System.out.println("ConcreteClassA: primitiveOperation2");
}

@Override
protected void hook() {
System.out.println("ConcreteClassA: hook");
}
}

// 具体类B
public class ConcreteClassB extends AbstractClass {
@Override
protected void primitiveOperation1() {
System.out.println("ConcreteClassB: primitiveOperation1");
}

@Override
protected void primitiveOperation2() {
System.out.println("ConcreteClassB: primitiveOperation2");
}
// 不重写钩子方法,使用默认实现
}

// 客户端使用
public class Client {
public static void main(String[] args) {
AbstractClass classA = new ConcreteClassA();
classA.templateMethod();

System.out.println();

AbstractClass classB = new ConcreteClassB();
classB.templateMethod();
}
}

示例:饮料制作流程

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// 抽象类:饮料
public abstract class Beverage {
// 模板方法
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
hook();
}

// 基本操作:煮水
private void boilWater() {
System.out.println("Boiling water");
}

// 基本操作:冲泡(子类实现)
protected abstract void brew();

// 基本操作:倒入杯中
private void pourInCup() {
System.out.println("Pouring into cup");
}

// 基本操作:添加调料(子类实现)
protected abstract void addCondiments();

// 钩子方法
protected void hook() {
// 默认实现
}
}

// 具体类:咖啡
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("Dripping Coffee through filter");
}

@Override
protected void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}

// 具体类:茶
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("Steeping the tea");
}

@Override
protected void addCondiments() {
System.out.println("Adding Lemon");
}

@Override
protected void hook() {
System.out.println("Tea is ready");
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
Beverage coffee = new Coffee();
System.out.println("Making coffee:");
coffee.prepareRecipe();

System.out.println();

Beverage tea = new Tea();
System.out.println("Making tea:");
tea.prepareRecipe();
}
}

4.9.6 优缺点

优点:

  • 封装了算法的骨架
  • 子类可以重定义算法的某些步骤
  • 符合开闭原则
  • 提高了代码的复用性

缺点:

  • 可能会导致类的数量增加
  • 模板方法可能会变得过于复杂

4.9.7 应用场景

  • 当多个类有相似的算法,但某些步骤不同时
  • 当需要控制子类的扩展时
  • 当需要在父类中定义算法的骨架,而在子类中实现具体步骤时

4.10 访问者模式(Visitor)

4.10.1 意图

表示一个作用于某对象结构中的各元素的操作。访问者模式使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

4.10.2 动机

当需要对一个对象结构中的元素执行不同的操作,而又不希望修改这些元素的类时,可以使用访问者模式。

4.10.3 结构

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
38
39
40
41
42
43
44
45
46
47
48
+----------------+
| Client |
+----------------+
| + operation() |
+----------------+
|
|
+----------------+
| ObjectStructure|
+----------------+
| - elements: |
| List<Element>|
| + accept(Visitor)|
+----------------+
|
|
+----------------+
| Element |
+----------------+
| + accept(Visitor)|
+----------------+
^
|
+----------------+ +----------------+
| ConcreteElementA | | ConcreteElementB |
+----------------+ +----------------+
| + accept(Visitor)|
| | | + accept(Visitor)|
+----------------+ +----------------+
| |
| |
+----------------+
| Visitor |
+----------------+
| + visit(ConcreteElementA)|
| + visit(ConcreteElementB)|
+----------------+
^
|
+----------------+ +----------------+
| ConcreteVisitor1 | | ConcreteVisitor2 |
+----------------+ +----------------+
| + visit(ConcreteElementA)|
| + visit(ConcreteElementB)|
+----------------+ +----------------+
| + visit(ConcreteElementA)|
| + visit(ConcreteElementB)|
+----------------+

4.10.4 参与者

  • Visitor:访问者接口,定义访问元素的方法
  • ConcreteVisitor:具体访问者,实现访问者接口
  • Element:元素接口,定义接受访问者的方法
  • ConcreteElement:具体元素,实现元素接口
  • ObjectStructure:对象结构,存储元素并接受访问者
  • Client:使用访问者和对象结构

4.10.5 实现

Java 实现:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// 访问者接口
public interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}

// 元素接口
public interface Element {
void accept(Visitor visitor);
}

// 具体元素A
public class ConcreteElementA implements Element {
private String name;

public ConcreteElementA(String name) {
this.name = name;
}

public String getName() {
return name;
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

// 具体元素B
public class ConcreteElementB implements Element {
private int value;

public ConcreteElementB(int value) {
this.value = value;
}

public int getValue() {
return value;
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

// 具体访问者1
public class ConcreteVisitor1 implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("Visitor1 visiting ConcreteElementA: " + element.getName());
}

@Override
public void visit(ConcreteElementB element) {
System.out.println("Visitor1 visiting ConcreteElementB: " + element.getValue());
}
}

// 具体访问者2
public class ConcreteVisitor2 implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("Visitor2 visiting ConcreteElementA: " + element.getName());
}

@Override
public void visit(ConcreteElementB element) {
System.out.println("Visitor2 visiting ConcreteElementB: " + element.getValue());
}
}

// 对象结构
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();

public void addElement(Element element) {
elements.add(element);
}

public void removeElement(Element element) {
elements.remove(element);
}

public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
ObjectStructure structure = new ObjectStructure();
structure.addElement(new ConcreteElementA("A1"));
structure.addElement(new ConcreteElementB(100));
structure.addElement(new ConcreteElementA("A2"));
structure.addElement(new ConcreteElementB(200));

System.out.println("Using Visitor1:");
structure.accept(new ConcreteVisitor1());

System.out.println("\nUsing Visitor2:");
structure.accept(new ConcreteVisitor2());
}
}

示例:购物车结算

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// 访问者接口
public interface ShoppingCartVisitor {
double visit(Book book);
double visit(Fruit fruit);
}

// 元素接口
public interface ItemElement {
double accept(ShoppingCartVisitor visitor);
}

// 具体元素:书
public class Book implements ItemElement {
private double price;
private String isbn;

public Book(double price, String isbn) {
this.price = price;
this.isbn = isbn;
}

public double getPrice() {
return price;
}

public String getIsbn() {
return isbn;
}

@Override
public double accept(ShoppingCartVisitor visitor) {
return visitor.visit(this);
}
}

// 具体元素:水果
public class Fruit implements ItemElement {
private double pricePerKg;
private double weight;
private String name;

public Fruit(double pricePerKg, double weight, String name) {
this.pricePerKg = pricePerKg;
this.weight = weight;
this.name = name;
}

public double getPricePerKg() {
return pricePerKg;
}

public double getWeight() {
return weight;
}

public String getName() {
return name;
}

@Override
public double accept(ShoppingCartVisitor visitor) {
return visitor.visit(this);
}
}

// 具体访问者:购物车访问者
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
@Override
public double visit(Book book) {
double cost = book.getPrice();
// 书有5%的折扣
if (cost > 50) {
cost -= cost * 0.05;
}
System.out.println("Book ISBN: " + book.getIsbn() + " cost: " + cost);
return cost;
}

@Override
public double visit(Fruit fruit) {
double cost = fruit.getPricePerKg() * fruit.getWeight();
System.out.println(fruit.getName() + " cost: " + cost);
return cost;
}
}

// 客户端使用
public class Client {
public static void main(String[] args) {
ItemElement[] items = {
new Book(20, "1234"),
new Book(100, "5678"),
new Fruit(10, 2, "Apple"),
new Fruit(5, 5, "Banana")
};

double total = calculateTotal(items);
System.out.println("Total cost: " + total);
}

private static double calculateTotal(ItemElement[] items) {
ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
double sum = 0;
for (ItemElement item : items) {
sum += item.accept(visitor);
}
return sum;
}
}

4.10.6 优缺点

优点:

  • 可以在不修改元素类的情况下添加新的操作
  • 可以集中相关的操作,分离不相关的操作
  • 符合单一职责原则
  • 符合开闭原则

缺点:

  • 增加了系统的复杂度
  • 可能会导致元素类和访问者类之间的耦合
  • 当添加新的元素类型时,需要修改所有的访问者类

4.10.7 应用场景

  • 当需要对一个对象结构中的元素执行不同的操作,而又不希望修改这些元素的类时
  • 当需要在不修改元素类的情况下添加新的操作时
  • 当需要集中相关的操作,分离不相关的操作时

第五部分:应用与实践

5.1 设计模式的选择

在选择设计模式时,需要考虑以下因素:

  1. 问题的性质:根据具体的问题选择合适的设计模式
  2. 系统的可扩展性:考虑系统未来的扩展需求
  3. 系统的可维护性:考虑系统的可维护性
  4. 系统的性能:考虑系统的性能需求
  5. 开发团队的经验:考虑开发团队对设计模式的熟悉程度

5.2 设计模式的组合

在实际应用中,通常需要组合使用多种设计模式来解决复杂的问题。以下是一些常见的设计模式组合:

  1. 单例模式 + 工厂方法模式:使用单例模式来管理工厂类
  2. 策略模式 + 工厂方法模式:使用工厂方法来创建策略对象
  3. 观察者模式 + 命令模式:使用命令模式来封装观察者的更新操作
  4. 装饰器模式 + 工厂方法模式:使用工厂方法来创建装饰后的对象
  5. 模板方法模式 + 策略模式:使用策略模式来替换模板方法中的某些步骤

5.3 设计模式的反模式

在使用设计模式时,需要避免以下反模式:

  1. 过度设计:为了使用设计模式而使用设计模式,导致系统过于复杂
  2. 模式误用:使用了不适合当前问题的设计模式
  3. 模式滥用:在不需要使用设计模式的地方使用设计模式
  4. 模式固化:过于严格地遵循设计模式的结构,而不考虑实际情况

5.4 设计模式的最佳实践

  1. 理解设计模式的本质:设计模式是一种思想和方法论,而不是现成的代码
  2. 根据问题选择合适的设计模式:不要为了使用设计模式而使用设计模式
  3. 灵活应用设计模式:根据实际情况调整设计模式的结构
  4. 结合面向对象设计原则:设计模式是面向对象设计原则的具体应用
  5. 持续学习和实践:通过学习和实践来加深对设计模式的理解

第六部分:总结与展望

6.1 设计模式的价值

设计模式的价值在于:

  1. 提供了一套通用的设计词汇:使开发者之间的沟通更加高效
  2. 展示了如何使用面向对象设计原则:帮助开发者构建更加灵活、可复用和可维护的软件系统
  3. 通过具体的代码示例和案例分析:说明了每种设计模式的应用场景和实现方法
  4. 强调了设计模式的灵活性和可扩展性:帮助开发者构建更加健壮和可维护的软件系统

6.2 设计模式的局限性

设计模式也有其局限性:

  1. 设计模式不是银弹:不能解决所有的软件设计问题
  2. 设计模式需要根据实际情况调整:不能生搬硬套
  3. 设计模式可能会增加系统的复杂度:在简单的系统中使用设计模式可能会适得其反
  4. 设计模式需要开发者具备一定的经验:需要开发者理解面向对象设计原则和设计模式的本质

6.3 未来的发展

随着软件技术的发展,设计模式也在不断演变:

  1. 新的设计模式不断涌现:随着新的编程范式和技术的出现,新的设计模式也在不断涌现
  2. 设计模式的应用范围不断扩大:设计模式不仅适用于面向对象编程,也适用于函数式编程等其他编程范式
  3. 设计模式的工具支持不断增强:越来越多的工具和框架开始支持设计模式的应用
  4. 设计模式的教育和培训不断加强:越来越多的开发者开始学习和应用设计模式

6.4 结语

《设计模式:可复用面向对象软件的基础》是一本经典的软件设计书籍,它系统地总结了 23 种常用的设计模式,为软件开发者提供了一套可复用的设计方案。通过学习和应用这些设计模式,开发者可以构建更加灵活、可复用和可维护的软件系统。

然而,设计模式不是银弹,不能解决所有的软件设计问题。在使用设计模式时,需要根据实际情况选择合适的设计模式,并灵活应用。同时,开发者还需要不断学习和实践,加深对设计模式的理解,以便更好地应用设计模式来解决实际问题。

最后,设计模式是一种思想和方法论,而不是现成的代码。开发者需要理解设计模式的本质,结合面向对象设计原则,根据实际情况灵活应用设计模式,才能真正发挥设计模式的价值。