第45章 现代C++设计模式

45.1 设计模式概述

45.1.1 设计模式的概念

设计模式是在软件设计中针对特定问题的通用、可重用的解决方案。它是在特定环境下解决特定问题的一套被反复使用的、经过分类的、代码设计经验的总结。

45.1.2 设计模式的分类

根据GoF(Gang of Four)的分类,设计模式可以分为三大类:

  • 创建型模式:处理对象的创建过程

    • 单例模式(Singleton)
    • 工厂方法模式(Factory Method)
    • 抽象工厂模式(Abstract Factory)
    • 建造者模式(Builder)
    • 原型模式(Prototype)
  • 结构型模式:处理对象之间的组合关系

    • 适配器模式(Adapter)
    • 桥接模式(Bridge)
    • 组合模式(Composite)
    • 装饰器模式(Decorator)
    • 外观模式(Facade)
    • 享元模式(Flyweight)
    • 代理模式(Proxy)
  • 行为型模式:处理对象之间的通信

    • 观察者模式(Observer)
    • 策略模式(Strategy)
    • 命令模式(Command)
    • 迭代器模式(Iterator)
    • 状态模式(State)
    • 模板方法模式(Template Method)
    • 访问者模式(Visitor)
    • 中介者模式(Mediator)
    • 备忘录模式(Memento)
    • 责任链模式(Chain of Responsibility)
    • 解释器模式(Interpreter)

45.1.3 设计模式的重要性

  • 代码重用:设计模式提供了经过验证的解决方案,避免重复造轮子
  • 可维护性:设计模式使代码更加清晰、结构化,易于理解和维护
  • 可扩展性:设计模式提供了灵活的架构,易于添加新功能
  • 标准化:设计模式为开发者提供了共同的语言和术语
  • 降低风险:使用经过验证的设计模式可以减少设计错误

45.1.4 现代C++中的设计模式

现代C++(C++11及以后)为设计模式的实现提供了许多新特性:

  • 智能指针std::unique_ptrstd::shared_ptr 用于资源管理
  • lambda表达式:用于简化回调和策略模式
  • 移动语义:提高性能,特别是在原型模式和建造者模式中
  • 右值引用:支持移动语义
  • 类型推导auto 关键字简化代码
  • 模板别名using 关键字提供更好的类型别名
  • constexpr:编译时计算
  • 委托构造函数:简化构造函数代码
  • 继承构造函数:简化继承关系
  • 强类型枚举enum class 提供类型安全的枚举

45.2 创建型设计模式

45.2.1 单例模式(Singleton)

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

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

// 私有构造函数
Singleton() {
// 初始化代码
}

// 私有析构函数
~Singleton() {
// 清理代码
}

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

public:
// 获取实例的静态方法
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}

// 销毁实例的静态方法
static void destroyInstance() {
if (instance != nullptr) {
delete instance;
instance = nullptr;
}
}

// 成员方法
void doSomething() {
// 实现
}
};

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

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

class Singleton {
private:
// 私有构造函数
Singleton() {
// 初始化代码
}

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

public:
// 获取实例的静态方法(线程安全)
static Singleton& getInstance() {
static Singleton instance; // C++11后线程安全
return instance;
}

// 成员方法
void doSomething() {
// 实现
}
};

45.2.1.3 应用场景

  • 配置管理:全局配置对象
  • 日志系统:全局日志记录器
  • 数据库连接池:管理数据库连接
  • 线程池:管理线程资源

45.2.2 工厂方法模式(Factory Method)

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

45.2.2.1 现代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
#include <memory>
#include <string>

// 产品接口
class Product {
public:
virtual ~Product() = default;
virtual std::string getName() const = 0;
};

// 具体产品A
class ConcreteProductA : public Product {
public:
std::string getName() const override {
return "Product A";
}
};

// 具体产品B
class ConcreteProductB : public Product {
public:
std::string getName() const override {
return "Product B";
}
};

// 创建者接口
class Creator {
public:
virtual ~Creator() = default;

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

// 业务逻辑
void someOperation() const {
auto product = createProduct();
std::cout << "Using " << product->getName() << std::endl;
}
};

// 具体创建者A
class ConcreteCreatorA : public Creator {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductA>();
}
};

// 具体创建者B
class ConcreteCreatorB : public Creator {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductB>();
}
};

// 使用示例
int main() {
std::unique_ptr<Creator> creatorA = std::make_unique<ConcreteCreatorA>();
creatorA->someOperation();

std::unique_ptr<Creator> creatorB = std::make_unique<ConcreteCreatorB>();
creatorB->someOperation();

return 0;
}

45.2.2.2 应用场景

  • 框架设计:框架需要由子类决定创建哪种对象
  • 插件系统:根据配置或用户选择创建不同的插件实例
  • 数据库访问:根据不同的数据库类型创建不同的连接对象

45.2.3 抽象工厂模式(Abstract Factory)

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

45.2.3.1 现代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
#include <memory>
#include <string>

// 产品A接口
class AbstractProductA {
public:
virtual ~AbstractProductA() = default;
virtual std::string getName() const = 0;
};

// 具体产品A1
class ConcreteProductA1 : public AbstractProductA {
public:
std::string getName() const override {
return "Product A1";
}
};

// 具体产品A2
class ConcreteProductA2 : public AbstractProductA {
public:
std::string getName() const override {
return "Product A2";
}
};

// 产品B接口
class AbstractProductB {
public:
virtual ~AbstractProductB() = default;
virtual std::string getName() const = 0;
};

// 具体产品B1
class ConcreteProductB1 : public AbstractProductB {
public:
std::string getName() const override {
return "Product B1";
}
};

// 具体产品B2
class ConcreteProductB2 : public AbstractProductB {
public:
std::string getName() const override {
return "Product B2";
}
};

// 抽象工厂接口
class AbstractFactory {
public:
virtual ~AbstractFactory() = default;
virtual std::unique_ptr<AbstractProductA> createProductA() = 0;
virtual std::unique_ptr<AbstractProductB> createProductB() = 0;
};

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

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

// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
public:
std::unique_ptr<AbstractProductA> createProductA() override {
return std::make_unique<ConcreteProductA2>();
}

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

// 使用示例
int main() {
std::unique_ptr<AbstractFactory> factory1 = std::make_unique<ConcreteFactory1>();
auto productA1 = factory1->createProductA();
auto productB1 = factory1->createProductB();
std::cout << "Factory 1: " << productA1->getName() << ", " << productB1->getName() << std::endl;

std::unique_ptr<AbstractFactory> factory2 = std::make_unique<ConcreteFactory2>();
auto productA2 = factory2->createProductA();
auto productB2 = factory2->createProductB();
std::cout << "Factory 2: " << productA2->getName() << ", " << productB2->getName() << std::endl;

return 0;
}

45.2.3.2 应用场景

  • 跨平台应用:为不同平台创建不同的UI组件
  • 主题系统:为不同主题创建不同的UI元素
  • 数据库访问:为不同数据库创建不同的连接和命令对象

45.2.4 建造者模式(Builder)

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

45.2.4.1 现代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
#include <memory>
#include <string>
#include <vector>

// 产品类
class Product {
public:
void addPart(const std::string& part) {
parts.push_back(part);
}

void show() const {
std::cout << "Product parts: " << std::endl;
for (const auto& part : parts) {
std::cout << "- " << part << std::endl;
}
}

private:
std::vector<std::string> parts;
};

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

// 具体建造者1
class ConcreteBuilder1 : public Builder {
public:
ConcreteBuilder1() : product(std::make_unique<Product>()) {}

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

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

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

std::unique_ptr<Product> getResult() override {
return std::move(product);
}

private:
std::unique_ptr<Product> product;
};

// 具体建造者2
class ConcreteBuilder2 : public Builder {
public:
ConcreteBuilder2() : product(std::make_unique<Product>()) {}

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

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

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

std::unique_ptr<Product> getResult() override {
return std::move(product);
}

private:
std::unique_ptr<Product> product;
};

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

// 使用示例
int main() {
Director director;

// 使用建造者1
ConcreteBuilder1 builder1;
director.construct(builder1);
auto product1 = builder1.getResult();
product1->show();

// 使用建造者2
ConcreteBuilder2 builder2;
director.construct(builder2);
auto product2 = builder2.getResult();
product2->show();

return 0;
}

45.2.4.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
#include <string>
#include <vector>

class Product {
public:
std::vector<std::string> parts;

void show() const {
std::cout << "Product parts: " << std::endl;
for (const auto& part : parts) {
std::cout << "- " << part << std::endl;
}
}
};

class Builder {
public:
Builder& addPartA() {
product.parts.push_back("Part A");
return *this;
}

Builder& addPartB() {
product.parts.push_back("Part B");
return *this;
}

Builder& addPartC() {
product.parts.push_back("Part C");
return *this;
}

Product build() {
return std::move(product);
}

private:
Product product;
};

// 使用示例
int main() {
Product product = Builder()
.addPartA()
.addPartB()
.addPartC()
.build();

product.show();

return 0;
}

45.2.4.3 应用场景

  • 复杂对象创建:当对象有很多可选参数时
  • 分步构建:当对象需要分步构建时
  • 不可变对象:当需要创建不可变对象时

45.2.5 原型模式(Prototype)

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

45.2.5.1 现代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
#include <memory>
#include <string>

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

// 具体原型1
class ConcretePrototype1 : public Prototype {
public:
ConcretePrototype1(const std::string& name) : name(name) {}

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

void show() const override {
std::cout << "ConcretePrototype1: " << name << std::endl;
}

private:
std::string name;
};

// 具体原型2
class ConcretePrototype2 : public Prototype {
public:
ConcretePrototype2(const std::string& name) : name(name) {}

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

void show() const override {
std::cout << "ConcretePrototype2: " << name << std::endl;
}

private:
std::string name;
};

// 使用示例
int main() {
// 创建原型
std::unique_ptr<Prototype> prototype1 = std::make_unique<ConcretePrototype1>("Prototype 1");
std::unique_ptr<Prototype> prototype2 = std::make_unique<ConcretePrototype2>("Prototype 2");

// 克隆原型
auto clone1 = prototype1->clone();
auto clone2 = prototype2->clone();

// 显示结果
prototype1->show();
clone1->show();
prototype2->show();
clone2->show();

return 0;
}

45.2.5.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
// 深拷贝示例
class Prototype {
public:
virtual ~Prototype() = default;
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual void show() const = 0;
};

class ConcretePrototype : public Prototype {
public:
ConcretePrototype(int value, const std::string& name)
: value(value), name(new std::string(name)) {}

// 深拷贝构造函数
ConcretePrototype(const ConcretePrototype& other)
: value(other.value), name(new std::string(*other.name)) {}

// 移动构造函数
ConcretePrototype(ConcretePrototype&& other) noexcept
: value(other.value), name(other.name) {
other.name = nullptr;
}

~ConcretePrototype() override {
delete name;
}

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

void show() const override {
std::cout << "Value: " << value << ", Name: " << *name << std::endl;
}

private:
int value;
std::string* name; // 指针成员
};

45.2.5.3 应用场景

  • 对象创建成本高:当对象创建成本较高时,克隆比新建更高效
  • 对象结构复杂:当对象结构复杂,创建过程繁琐时
  • 运行时动态创建:当需要在运行时动态创建对象时

45.3 结构型设计模式

45.3.1 适配器模式(Adapter)

适配器模式将一个类的接口转换成客户希望的另一个接口。适配器模式使得那些接口不兼容的类可以一起工作。

45.3.1.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
// 目标接口
class Target {
public:
virtual ~Target() = default;
virtual void request() const = 0;
};

// 被适配者
class Adaptee {
public:
void specificRequest() const {
std::cout << "Adaptee's specific request" << std::endl;
}
};

// 类适配器
class ClassAdapter : public Target, private Adaptee {
public:
void request() const override {
specificRequest();
}
};

// 使用示例
int main() {
std::unique_ptr<Target> target = std::make_unique<ClassAdapter>();
target->request();

return 0;
}

45.3.1.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
// 目标接口
class Target {
public:
virtual ~Target() = default;
virtual void request() const = 0;
};

// 被适配者
class Adaptee {
public:
void specificRequest() const {
std::cout << "Adaptee's specific request" << std::endl;
}
};

// 对象适配器
class ObjectAdapter : public Target {
public:
ObjectAdapter(std::unique_ptr<Adaptee> adaptee) : adaptee(std::move(adaptee)) {}

void request() const override {
adaptee->specificRequest();
}

private:
std::unique_ptr<Adaptee> adaptee;
};

// 使用示例
int main() {
std::unique_ptr<Target> target = std::make_unique<ObjectAdapter>(std::make_unique<Adaptee>());
target->request();

return 0;
}

45.3.1.3 应用场景

  • 接口不兼容:当需要使用一个接口不兼容的类时
  • 第三方库集成:当集成第三方库时,其接口与现有代码不匹配
  • 旧系统集成:当需要集成旧系统时,其接口与新系统不匹配

45.3.2 桥接模式(Bridge)

桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。

45.3.2.1 现代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
#include <memory>
#include <string>

// 实现接口
class Implementor {
public:
virtual ~Implementor() = default;
virtual void operationImpl() const = 0;
};

// 具体实现A
class ConcreteImplementorA : public Implementor {
public:
void operationImpl() const override {
std::cout << "ConcreteImplementorA's operation" << std::endl;
}
};

// 具体实现B
class ConcreteImplementorB : public Implementor {
public:
void operationImpl() const override {
std::cout << "ConcreteImplementorB's operation" << std::endl;
}
};

// 抽象类
class Abstraction {
public:
Abstraction(std::unique_ptr<Implementor> implementor) : implementor(std::move(implementor)) {}
virtual ~Abstraction() = default;

virtual void operation() const {
implementor->operationImpl();
}

protected:
std::unique_ptr<Implementor> implementor;
};

// 扩展抽象类
class RefinedAbstraction : public Abstraction {
public:
using Abstraction::Abstraction;

void operation() const override {
std::cout << "RefinedAbstraction's operation: " << std::endl;
Abstraction::operation();
}
};

// 使用示例
int main() {
// 使用实现A
std::unique_ptr<Abstraction> abstractionA = std::make_unique<RefinedAbstraction>(std::make_unique<ConcreteImplementorA>());
abstractionA->operation();

// 使用实现B
std::unique_ptr<Abstraction> abstractionB = std::make_unique<RefinedAbstraction>(std::make_unique<ConcreteImplementorB>());
abstractionB->operation();

return 0;
}

45.3.2.2 应用场景

  • 多维度变化:当一个类有多个维度的变化时
  • 平台独立性:当需要实现平台独立的代码时
  • UI框架:当UI框架需要与具体实现分离时

45.3.3 组合模式(Composite)

组合模式将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

45.3.3.1 现代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
#include <memory>
#include <vector>
#include <string>

// 组件接口
class Component {
public:
virtual ~Component() = default;
virtual void add(std::unique_ptr<Component> component) {
// 默认实现,叶子节点不支持
}
virtual void remove(Component* component) {
// 默认实现,叶子节点不支持
}
virtual Component* getChild(int index) {
// 默认实现,叶子节点不支持
return nullptr;
}
virtual void operation() const = 0;
};

// 叶子节点
class Leaf : public Component {
public:
Leaf(const std::string& name) : name(name) {}

void operation() const override {
std::cout << "Leaf: " << name << std::endl;
}

private:
std::string name;
};

// 复合节点
class Composite : public Component {
public:
Composite(const std::string& name) : name(name) {}

void add(std::unique_ptr<Component> component) override {
children.push_back(std::move(component));
}

void remove(Component* component) override {
// 查找并移除组件
for (auto it = children.begin(); it != children.end(); ++it) {
if (it->get() == component) {
children.erase(it);
break;
}
}
}

Component* getChild(int index) override {
if (index >= 0 && index < children.size()) {
return children[index].get();
}
return nullptr;
}

void operation() const override {
std::cout << "Composite: " << name << std::endl;
for (const auto& child : children) {
child->operation();
}
}

private:
std::string name;
std::vector<std::unique_ptr<Component>> children;
};

// 使用示例
int main() {
// 创建复合节点
auto root = std::make_unique<Composite>("Root");

// 添加叶子节点
root->add(std::make_unique<Leaf>("Leaf 1"));
root->add(std::make_unique<Leaf>("Leaf 2"));

// 创建子复合节点
auto branch = std::make_unique<Composite>("Branch");
branch->add(std::make_unique<Leaf>("Leaf 3"));
branch->add(std::make_unique<Leaf>("Leaf 4"));

// 添加子复合节点到根
root->add(std::move(branch));

// 执行操作
root->operation();

return 0;
}

45.3.3.2 应用场景

  • 树形结构:当需要处理树形结构时
  • 文件系统:文件和目录的层次结构
  • UI组件:窗口和控件的层次结构
  • 组织架构:公司和部门的层次结构

45.3.4 装饰器模式(Decorator)

装饰器模式动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。

45.3.4.1 现代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
#include <memory>
#include <string>

// 组件接口
class Component {
public:
virtual ~Component() = default;
virtual std::string operation() const = 0;
};

// 具体组件
class ConcreteComponent : public Component {
public:
std::string operation() const override {
return "ConcreteComponent";
}
};

// 装饰器抽象类
class Decorator : public Component {
public:
Decorator(std::unique_ptr<Component> component) : component(std::move(component)) {}

std::string operation() const override {
return component->operation();
}

protected:
std::unique_ptr<Component> component;
};

// 具体装饰器A
class ConcreteDecoratorA : public Decorator {
public:
using Decorator::Decorator;

std::string operation() const override {
return "ConcreteDecoratorA(" + Decorator::operation() + ")";
}
};

// 具体装饰器B
class ConcreteDecoratorB : public Decorator {
public:
using Decorator::Decorator;

std::string operation() const override {
return "ConcreteDecoratorB(" + Decorator::operation() + ")";
}
};

// 使用示例
int main() {
// 创建基本组件
std::unique_ptr<Component> component = std::make_unique<ConcreteComponent>();
std::cout << "Basic component: " << component->operation() << std::endl;

// 添加装饰器A
std::unique_ptr<Component> decoratorA = std::make_unique<ConcreteDecoratorA>(std::move(component));
std::cout << "With decorator A: " << decoratorA->operation() << std::endl;

// 添加装饰器B
std::unique_ptr<Component> decoratorB = std::make_unique<ConcreteDecoratorB>(std::move(decoratorA));
std::cout << "With decorator B: " << decoratorB->operation() << std::endl;

return 0;
}

45.3.4.2 应用场景

  • 动态添加功能:当需要动态地给对象添加功能时
  • 功能组合:当需要组合多个功能时
  • 避免子类爆炸:当使用继承会导致大量子类时

45.3.5 外观模式(Facade)

外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。

45.3.5.1 现代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
#include <memory>

// 子系统1
class Subsystem1 {
public:
void operation1() const {
std::cout << "Subsystem1 operation" << std::endl;
}
};

// 子系统2
class Subsystem2 {
public:
void operation2() const {
std::cout << "Subsystem2 operation" << std::endl;
}
};

// 子系统3
class Subsystem3 {
public:
void operation3() const {
std::cout << "Subsystem3 operation" << std::endl;
}
};

// 外观类
class Facade {
public:
Facade() {
subsystem1 = std::make_unique<Subsystem1>();
subsystem2 = std::make_unique<Subsystem2>();
subsystem3 = std::make_unique<Subsystem3>();
}

void operation() const {
std::cout << "Facade operation:" << std::endl;
subsystem1->operation1();
subsystem2->operation2();
subsystem3->operation3();
}

private:
std::unique_ptr<Subsystem1> subsystem1;
std::unique_ptr<Subsystem2> subsystem2;
std::unique_ptr<Subsystem3> subsystem3;
};

// 使用示例
int main() {
Facade facade;
facade.operation();

return 0;
}

45.3.5.2 应用场景

  • 复杂子系统:当子系统非常复杂时
  • API简化:当需要简化API时
  • 分层架构:当需要在不同层次之间创建接口时

45.3.6 享元模式(Flyweight)

享元模式运用共享技术有效地支持大量细粒度的对象。

45.3.6.1 现代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
#include <memory>
#include <string>
#include <unordered_map>

// 享元接口
class Flyweight {
public:
virtual ~Flyweight() = default;
virtual void operation(const std::string& extrinsicState) const = 0;
};

// 具体享元
class ConcreteFlyweight : public Flyweight {
public:
ConcreteFlyweight(const std::string& intrinsicState) : intrinsicState(intrinsicState) {}

void operation(const std::string& extrinsicState) const override {
std::cout << "ConcreteFlyweight: Intrinsic = " << intrinsicState
<< ", Extrinsic = " << extrinsicState << std::endl;
}

private:
std::string intrinsicState; // 内部状态,可共享
};

// 享元工厂
class FlyweightFactory {
public:
std::shared_ptr<Flyweight> getFlyweight(const std::string& key) {
// 查找享元对象
auto it = flyweights.find(key);
if (it != flyweights.end()) {
return it->second;
}

// 创建新的享元对象
auto flyweight = std::make_shared<ConcreteFlyweight>(key);
flyweights[key] = flyweight;
return flyweight;
}

void listFlyweights() const {
std::cout << "FlyweightFactory: I have " << flyweights.size() << " flyweights" << std::endl;
for (const auto& pair : flyweights) {
std::cout << "- " << pair.first << std::endl;
}
}

private:
std::unordered_map<std::string, std::shared_ptr<Flyweight>> flyweights;
};

// 使用示例
int main() {
FlyweightFactory factory;

// 获取享元对象
auto flyweight1 = factory.getFlyweight("A");
auto flyweight2 = factory.getFlyweight("B");
auto flyweight3 = factory.getFlyweight("A"); // 复用已存在的享元

// 使用享元对象
flyweight1->operation("X");
flyweight2->operation("Y");
flyweight3->operation("Z");

// 列出所有享元
factory.listFlyweights();

return 0;
}

45.3.6.2 应用场景

  • 大量细粒度对象:当需要创建大量细粒度对象时
  • 内存限制:当内存有限制时
  • 对象共享:当对象可以共享内部状态时

45.3.7 代理模式(Proxy)

代理模式为其他对象提供一种代理以控制对这个对象的访问。

45.3.7.1 现代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
#include <memory>
#include <string>

// 主题接口
class Subject {
public:
virtual ~Subject() = default;
virtual void request() const = 0;
};

// 真实主题
class RealSubject : public Subject {
public:
void request() const override {
std::cout << "RealSubject: Handling request" << std::endl;
}
};

// 代理
class Proxy : public Subject {
public:
Proxy(std::unique_ptr<Subject> realSubject) : realSubject(std::move(realSubject)) {}

void request() const override {
if (checkAccess()) {
realSubject->request();
logAccess();
}
}

private:
bool checkAccess() const {
std::cout << "Proxy: Checking access prior to requesting a service" << std::endl;
return true;
}

void logAccess() const {
std::cout << "Proxy: Logging the time of request" << std::endl;
}

std::unique_ptr<Subject> realSubject;
};

// 使用示例
int main() {
std::cout << "Client: Executing the client code with a real subject:" << std::endl;
std::unique_ptr<Subject> realSubject = std::make_unique<RealSubject>();
realSubject->request();

std::cout << "\nClient: Executing the same client code with a proxy:" << std::endl;
std::unique_ptr<Subject> proxy = std::make_unique<Proxy>(std::make_unique<RealSubject>());
proxy->request();

return 0;
}

45.3.7.2 代理模式的变体

  • 远程代理:控制对远程对象的访问
  • 虚拟代理:按需创建开销大的对象
  • 保护代理:控制对对象的访问权限
  • 智能引用:在访问对象时执行额外的操作

45.3.7.3 应用场景

  • 远程服务:当需要访问远程对象时
  • 资源密集型对象:当对象创建成本高时
  • 权限控制:当需要控制访问权限时
  • 日志记录:当需要记录访问日志时

45.4 行为型设计模式

45.4.1 观察者模式(Observer)

观察者模式定义了对象之间的一对多依赖关系,使得当一个对象状态发生变化时,所有依赖它的对象都会自动收到通知并更新。

45.4.1.1 现代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
#include <memory>
#include <vector>
#include <string>

// 前向声明
class Subject;

// 观察者接口
class Observer {
public:
virtual ~Observer() = default;
virtual void update(const Subject& subject) = 0;
};

// 主题接口
class Subject {
public:
virtual ~Subject() = default;

void attach(std::shared_ptr<Observer> observer) {
observers.push_back(observer);
}

void detach(std::shared_ptr<Observer> observer) {
for (auto it = observers.begin(); it != observers.end(); ++it) {
if (it->lock() == observer) {
observers.erase(it);
break;
}
}
}

void notify() {
for (const auto& weakObserver : observers) {
if (auto observer = weakObserver.lock()) {
observer->update(*this);
}
}
}

virtual int getState() const = 0;
virtual void setState(int state) = 0;

private:
std::vector<std::weak_ptr<Observer>> observers;
};

// 具体主题
class ConcreteSubject : public Subject {
public:
int getState() const override {
return state;
}

void setState(int state) override {
this->state = state;
notify();
}

private:
int state;
};

// 具体观察者A
class ConcreteObserverA : public Observer {
public:
void update(const Subject& subject) override {
state = subject.getState();
std::cout << "ConcreteObserverA: Updated state to " << state << std::endl;
}

private:
int state;
};

// 具体观察者B
class ConcreteObserverB : public Observer {
public:
void update(const Subject& subject) override {
state = subject.getState();
std::cout << "ConcreteObserverB: Updated state to " << state << std::endl;
}

private:
int state;
};

// 使用示例
int main() {
// 创建主题
std::shared_ptr<Subject> subject = std::make_shared<ConcreteSubject>();

// 创建观察者
std::shared_ptr<Observer> observerA = std::make_shared<ConcreteObserverA>();
std::shared_ptr<Observer> observerB = std::make_shared<ConcreteObserverB>();

// 注册观察者
subject->attach(observerA);
subject->attach(observerB);

// 更改主题状态
std::dynamic_pointer_cast<ConcreteSubject>(subject)->setState(10);
std::dynamic_pointer_cast<ConcreteSubject>(subject)->setState(20);

// 移除一个观察者
subject->detach(observerA);

// 再次更改主题状态
std::dynamic_pointer_cast<ConcreteSubject>(subject)->setState(30);

return 0;
}

45.4.1.2 应用场景

  • 事件处理:当需要处理事件时
  • 模型-视图-控制器:当使用MVC架构时
  • 发布-订阅系统:当需要实现发布-订阅模式时

45.4.2 策略模式(Strategy)

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。

45.4.2.1 现代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
#include <memory>
#include <string>

// 策略接口
class Strategy {
public:
virtual ~Strategy() = default;
virtual std::string doOperation(const std::string& data) const = 0;
};

// 具体策略A
class ConcreteStrategyA : public Strategy {
public:
std::string doOperation(const std::string& data) const override {
std::string result = data;
// 实现具体算法A
std::reverse(result.begin(), result.end());
return "ConcreteStrategyA: " + result;
}
};

// 具体策略B
class ConcreteStrategyB : public Strategy {
public:
std::string doOperation(const std::string& data) const override {
std::string result = data;
// 实现具体算法B
for (char& c : result) {
if (std::isalpha(c)) {
c = std::toupper(c);
}
}
return "ConcreteStrategyB: " + result;
}
};

// 上下文类
class Context {
public:
Context(std::unique_ptr<Strategy> strategy) : strategy(std::move(strategy)) {}

void setStrategy(std::unique_ptr<Strategy> strategy) {
this->strategy = std::move(strategy);
}

std::string executeStrategy(const std::string& data) const {
return strategy->doOperation(data);
}

private:
std::unique_ptr<Strategy> strategy;
};

// 使用示例
int main() {
// 创建上下文并使用策略A
Context context(std::make_unique<ConcreteStrategyA>());
std::cout << context.executeStrategy("Hello World") << std::endl;

// 切换到策略B
context.setStrategy(std::make_unique<ConcreteStrategyB>());
std::cout << context.executeStrategy("Hello World") << std::endl;

return 0;
}

45.4.2.2 使用lambda表达式简化

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
#include <functional>
#include <string>

class Context {
public:
using Strategy = std::function<std::string(const std::string&)>;

Context(Strategy strategy) : strategy(std::move(strategy)) {}

void setStrategy(Strategy strategy) {
this->strategy = std::move(strategy);
}

std::string executeStrategy(const std::string& data) const {
return strategy(data);
}

private:
Strategy strategy;
};

// 使用示例
int main() {
// 使用lambda表达式作为策略
Context context([](const std::string& data) {
std::string result = data;
std::reverse(result.begin(), result.end());
return "Reversed: " + result;
});

std::cout << context.executeStrategy("Hello World") << std::endl;

// 切换策略
context.setStrategy([](const std::string& data) {
std::string result = data;
for (char& c : result) {
if (std::isalpha(c)) {
c = std::toupper(c);
}
}
return "Uppercase: " + result;
});

std::cout << context.executeStrategy("Hello World") << std::endl;

return 0;
}

45.4.2.3 应用场景

  • 算法选择:当需要在运行时选择算法时
  • 排序策略:当需要不同的排序算法时
  • 验证策略:当需要不同的验证规则时
  • 支付方式:当需要不同的支付方式时

45.4.3 命令模式(Command)

命令模式将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

45.4.3.1 现代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
#include <memory>
#include <vector>

// 接收者
class Receiver {
public:
void action() const {
std::cout << "Receiver: Action performed" << std::endl;
}

void undoAction() const {
std::cout << "Receiver: Action undone" << std::endl;
}
};

// 命令接口
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
};

// 具体命令
class ConcreteCommand : public Command {
public:
ConcreteCommand(std::shared_ptr<Receiver> receiver) : receiver(receiver) {}

void execute() override {
receiver->action();
}

void undo() override {
receiver->undoAction();
}

private:
std::shared_ptr<Receiver> receiver;
};

// 空命令
class NoCommand : public Command {
public:
void execute() override {
// 什么都不做
}

void undo() override {
// 什么都不做
}
};

// 调用者
class Invoker {
public:
void setCommand(std::unique_ptr<Command> command) {
this->command = std::move(command);
}

void executeCommand() {
command->execute();
history.push_back(command.get());
}

void undoCommand() {
if (!history.empty()) {
history.back()->undo();
history.pop_back();
}
}

private:
std::unique_ptr<Command> command;
std::vector<Command*> history;
};

// 使用示例
int main() {
// 创建接收者
std::shared_ptr<Receiver> receiver = std::make_shared<Receiver>();

// 创建命令
std::unique_ptr<Command> command = std::make_unique<ConcreteCommand>(receiver);

// 创建调用者
Invoker invoker;
invoker.setCommand(std::move(command));

// 执行命令
invoker.executeCommand();

// 撤销命令
invoker.undoCommand();

return 0;
}

45.4.3.2 应用场景

  • 菜单操作:当需要实现菜单操作时
  • 撤销/重做:当需要支持撤销和重做操作时
  • 事务处理:当需要实现事务时
  • 队列请求:当需要队列处理请求时

45.4.4 迭代器模式(Iterator)

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

45.4.4.1 现代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
#include <memory>
#include <vector>

// 前向声明
class Iterator;
class ConcreteIterator;

// 聚合接口
class Aggregate {
public:
virtual ~Aggregate() = default;
virtual std::unique_ptr<Iterator> createIterator() = 0;
virtual int size() const = 0;
virtual int get(int index) const = 0;
};

// 迭代器接口
class Iterator {
public:
virtual ~Iterator() = default;
virtual bool hasNext() const = 0;
virtual int next() = 0;
};

// 具体聚合
class ConcreteAggregate : public Aggregate {
public:
void add(int value) {
items.push_back(value);
}

std::unique_ptr<Iterator> createIterator() override {
return std::make_unique<ConcreteIterator>(this);
}

int size() const override {
return items.size();
}

int get(int index) const override {
return items[index];
}

private:
std::vector<int> items;
};

// 具体迭代器
class ConcreteIterator : public Iterator {
public:
ConcreteIterator(ConcreteAggregate* aggregate) : aggregate(aggregate), index(0) {}

bool hasNext() const override {
return index < aggregate->size();
}

int next() override {
return aggregate->get(index++);
}

private:
ConcreteAggregate* aggregate;
int index;
};

// 使用示例
int main() {
// 创建聚合
std::unique_ptr<ConcreteAggregate> aggregate = std::make_unique<ConcreteAggregate>();

// 添加元素
aggregate->add(1);
aggregate->add(2);
aggregate->add(3);
aggregate->add(4);
aggregate->add(5);

// 创建迭代器
std::unique_ptr<Iterator> iterator = aggregate->createIterator();

// 遍历聚合
std::cout << "Iterating over aggregate: " << std::endl;
while (iterator->hasNext()) {
std::cout << iterator->next() << " " << std::endl;
}

return 0;
}

45.4.4.2 使用STL迭代器

现代C++中,STL已经提供了丰富的迭代器实现,我们可以直接使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <vector>
#include <list>
#include <map>
#include <iostream>

int main() {
// 使用vector的迭代器
std::vector<int> vec = {1, 2, 3, 4, 5};
std::cout << "Vector elements: " << std::endl;
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " " << std::endl;
}

// 使用范围for循环(C++11及以后)
std::cout << "Vector elements (range for): " << std::endl;
for (int value : vec) {
std::cout << value << " " << std::endl;
}

return 0;
}

45.4.4.3 应用场景

  • 集合遍历:当需要遍历集合而不暴露其内部结构时
  • 多态遍历:当需要统一遍历不同类型的集合时
  • 只读遍历:当需要提供只读访问时

45.4.5 状态模式(State)

状态模式允许对象在内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

45.4.5.1 现代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
#include <memory>

// 前向声明
class Context;

// 状态接口
class State {
public:
virtual ~State() = default;
virtual void handle(Context* context) = 0;
};

// 具体状态A
class ConcreteStateA : public State {
public:
void handle(Context* context) override;
};

// 具体状态B
class ConcreteStateB : public State {
public:
void handle(Context* context) override;
};

// 上下文类
class Context {
public:
Context(std::unique_ptr<State> state) : state(std::move(state)) {}

void setState(std::unique_ptr<State> state) {
this->state = std::move(state);
}

void request() {
state->handle(this);
}

private:
std::unique_ptr<State> state;
};

// 实现具体状态A的handle方法
void ConcreteStateA::handle(Context* context) {
std::cout << "ConcreteStateA: Handling request" << std::endl;
// 切换到状态B
context->setState(std::make_unique<ConcreteStateB>());
}

// 实现具体状态B的handle方法
void ConcreteStateB::handle(Context* context) {
std::cout << "ConcreteStateB: Handling request" << std::endl;
// 切换到状态A
context->setState(std::make_unique<ConcreteStateA>());
}

// 使用示例
int main() {
// 创建上下文并初始化为状态A
Context context(std::make_unique<ConcreteStateA>());

// 发送请求
context.request(); // 状态A处理,切换到状态B
context.request(); // 状态B处理,切换到状态A
context.request(); // 状态A处理,切换到状态B

return 0;
}

45.4.5.2 应用场景

  • 状态转换:当对象有多个状态,且状态转换有明确规则时
  • 有限状态机:当需要实现有限状态机时
  • 行为变化:当对象的行为依赖于其状态时

45.4.6 模板方法模式(Template Method)

模板方法模式定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

45.4.6.1 现代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
#include <iostream>

// 抽象基类
class AbstractClass {
public:
virtual ~AbstractClass() = default;

// 模板方法
void templateMethod() {
primitiveOperation1();
primitiveOperation2();
hook();
}

protected:
// 抽象方法,子类必须实现
virtual void primitiveOperation1() = 0;
virtual void primitiveOperation2() = 0;

// 钩子方法,子类可以选择覆盖
virtual void hook() {
std::cout << "AbstractClass: Default hook implementation" << std::endl;
}
};

// 具体子类A
class ConcreteClassA : public AbstractClass {
protected:
void primitiveOperation1() override {
std::cout << "ConcreteClassA: primitiveOperation1" << std::endl;
}

void primitiveOperation2() override {
std::cout << "ConcreteClassA: primitiveOperation2" << std::endl;
}
};

// 具体子类B
class ConcreteClassB : public AbstractClass {
protected:
void primitiveOperation1() override {
std::cout << "ConcreteClassB: primitiveOperation1" << std::endl;
}

void primitiveOperation2() override {
std::cout << "ConcreteClassB: primitiveOperation2" << std::endl;
}

void hook() override {
std::cout << "ConcreteClassB: Overridden hook implementation" << std::endl;
}
};

// 使用示例
int main() {
std::cout << "Client: Testing ConcreteClassA" << std::endl;
AbstractClass* concreteA = new ConcreteClassA();
concreteA->templateMethod();
delete concreteA;

std::cout << "\nClient: Testing ConcreteClassB" << std::endl;
AbstractClass* concreteB = new ConcreteClassB();
concreteB->templateMethod();
delete concreteB;

return 0;
}

45.4.6.2 应用场景

  • 算法骨架:当需要定义算法骨架,而将具体实现延迟到子类时
  • 代码复用:当多个子类共享相同的算法结构时
  • 控制子类扩展:当需要控制子类的扩展点时

45.4.7 访问者模式(Visitor)

访问者模式表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

45.4.7.1 现代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
#include <memory>
#include <vector>

// 前向声明
class ConcreteElementA;
class ConcreteElementB;

// 访问者接口
class Visitor {
public:
virtual ~Visitor() = default;
virtual void visit(ConcreteElementA* element) = 0;
virtual void visit(ConcreteElementB* element) = 0;
};

// 元素接口
class Element {
public:
virtual ~Element() = default;
virtual void accept(Visitor* visitor) = 0;
};

// 具体元素A
class ConcreteElementA : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visit(this);
}

void operationA() {
std::cout << "ConcreteElementA: operationA" << std::endl;
}
};

// 具体元素B
class ConcreteElementB : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visit(this);
}

void operationB() {
std::cout << "ConcreteElementB: operationB" << std::endl;
}
};

// 具体访问者A
class ConcreteVisitorA : public Visitor {
public:
void visit(ConcreteElementA* element) override {
std::cout << "ConcreteVisitorA: visiting ConcreteElementA" << std::endl;
element->operationA();
}

void visit(ConcreteElementB* element) override {
std::cout << "ConcreteVisitorA: visiting ConcreteElementB" << std::endl;
element->operationB();
}
};

// 具体访问者B
class ConcreteVisitorB : public Visitor {
public:
void visit(ConcreteElementA* element) override {
std::cout << "ConcreteVisitorB: visiting ConcreteElementA" << std::endl;
element->operationA();
}

void visit(ConcreteElementB* element) override {
std::cout << "ConcreteVisitorB: visiting ConcreteElementB" << std::endl;
element->operationB();
}
};

// 对象结构
class ObjectStructure {
public:
void addElement(std::unique_ptr<Element> element) {
elements.push_back(std::move(element));
}

void accept(Visitor* visitor) {
for (const auto& element : elements) {
element->accept(visitor);
}
}

private:
std::vector<std::unique_ptr<Element>> elements;
};

// 使用示例
int main() {
// 创建对象结构
ObjectStructure objectStructure;
objectStructure.addElement(std::make_unique<ConcreteElementA>());
objectStructure.addElement(std::make_unique<ConcreteElementB>());

// 创建访问者A并访问对象结构
std::cout << "Using ConcreteVisitorA:" << std::endl;
ConcreteVisitorA visitorA;
objectStructure.accept(&visitorA);

// 创建访问者B并访问对象结构
std::cout << "\nUsing ConcreteVisitorB:" << std::endl;
ConcreteVisitorB visitorB;
objectStructure.accept(&visitorB);

return 0;
}

45.4.7.2 应用场景

  • 复杂对象结构:当对象结构复杂,且需要对其中的元素执行不同操作时
  • 新增操作:当需要为对象结构添加新操作,而不修改元素类时
  • 分离算法:当需要将算法与对象结构分离时

45.5 现代C++中的设计模式

45.5.1 智能指针与设计模式

现代C++的智能指针(std::unique_ptrstd::shared_ptrstd::weak_ptr)为设计模式的实现提供了更安全、更简洁的方式:

  • 单例模式:使用std::unique_ptr或静态局部变量管理实例
  • 工厂方法:返回std::unique_ptrstd::shared_ptr
  • 抽象工厂:返回智能指针
  • 建造者模式:返回std::unique_ptr
  • 原型模式:使用std::unique_ptrstd::shared_ptr
  • 适配器模式:使用智能指针管理被适配者
  • 桥接模式:使用智能指针管理实现
  • 组合模式:使用std::unique_ptr管理子组件
  • 装饰器模式:使用std::unique_ptr管理被装饰对象
  • 代理模式:使用std::unique_ptr管理真实对象
  • 观察者模式:使用std::weak_ptr避免循环引用
  • 命令模式:使用智能指针管理命令和接收者

45.5.2 Lambda表达式与设计模式

Lambda表达式为设计模式的实现提供了更简洁的方式:

  • 策略模式:使用lambda作为策略
  • 命令模式:使用lambda作为命令
  • 观察者模式:使用lambda作为回调
  • 访问者模式:使用lambda作为访问者

45.5.3 移动语义与设计模式

移动语义(C++11引入)提高了设计模式实现的性能:

  • 原型模式:使用移动构造函数提高克隆性能
  • 建造者模式:使用移动语义返回产品
  • 工厂方法:使用移动语义返回产品

45.5.4 模板与设计模式

模板为设计模式的实现提供了更灵活的方式:

  • 策略模式:使用模板参数指定策略
  • 访问者模式:使用模板实现通用访问者
  • 工厂方法:使用模板创建不同类型的对象

45.6 设计模式的最佳实践

45.6.1 设计模式的选择

  • 理解问题:首先要理解问题的本质
  • 选择合适的模式:根据问题选择最适合的设计模式
  • 考虑上下文:考虑项目的具体上下文和约束
  • 不要过度设计:不要为了使用设计模式而使用设计模式

45.6.2 设计模式的实现

  • 遵循SOLID原则

    • 单一职责原则:一个类只负责一个功能领域
    • 开放-封闭原则:对扩展开放,对修改封闭
    • 里氏替换原则:子类可以替换父类
    • 接口隔离原则:使用多个专门的接口而不是单一的总接口
    • 依赖倒置原则:依赖于抽象而不是具体实现
  • 使用现代C++特性:利用智能指针、lambda表达式、移动语义等现代C++特性

  • 保持简洁:设计模式的实现应该简洁明了

  • 文档化:为设计模式的使用添加文档

  • 测试:为设计模式的实现添加测试

45.6.3 设计模式的演化

设计模式不是一成不变的,它们会随着语言和技术的发展而演化:

  • 从传统C++到现代C++:使用智能指针、lambda表达式等现代特性
  • 从面向对象到函数式:结合函数式编程思想
  • 从静态到动态:使用运行时多态和反射
  • 从单一模式到模式组合:组合使用多个设计模式

45.7 设计模式的实际应用

45.7.1 框架中的设计模式

许多流行的C++框架都使用了设计模式:

  • Qt:使用了观察者模式(信号槽)、工厂方法、单例模式等
  • Boost:使用了各种设计模式,如智能指针(代理模式的变体)、策略模式等
  • STL:使用了迭代器模式、策略模式、适配器模式等

45.7.2 企业应用中的设计模式

  • MVC:模型-视图-控制器模式,用于UI开发
  • DAO:数据访问对象模式,用于数据库访问
  • Service Locator:服务定位器模式,用于依赖管理
  • Dependency Injection:依赖注入模式,用于控制反转

45.7.3 游戏开发中的设计模式

  • 游戏循环:模板方法模式的变体
  • 实体组件系统:组合模式的变体
  • 状态管理:状态模式
  • AI行为:策略模式、状态模式、行为树

45.8 小结

本章介绍了现代C++中的设计模式,包括:

  • 设计模式概述:设计模式的概念、分类和重要性
  • 创建型设计模式:单例模式、工厂方法、抽象工厂、建造者模式、原型模式
  • 结构型设计模式:适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式
  • 行为型设计模式:观察者模式、策略模式、命令模式、迭代器模式、状态模式、模板方法模式、访问者模式
  • 现代C++中的设计模式:智能指针、lambda表达式、移动语义、模板与设计模式的结合
  • 设计模式的最佳实践:设计模式的选择、实现、演化
  • 设计模式的实际应用:框架、企业应用、游戏开发中的设计模式

设计模式是C++编程中的重要工具,它们提供了经过验证的解决方案,可以帮助我们编写更清晰、更可维护、更可扩展的代码。通过学习和应用设计模式,我们可以提高自己的编程水平,更好地解决复杂的软件设计问题。

同时,我们也应该认识到,设计模式不是银弹,它们只是工具,需要根据具体情况合理使用。在实际开发中,我们应该根据问题的本质,选择合适的设计模式,并结合现代C++的特性,创造出既优雅又高效的解决方案。