设计模式

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
#include <iostream>
// 抽象类,定义了模板方法和步骤
class Beverage {
public:
// 模板方法,定义了制作饮料的步骤
void prepareRecipe() {
boilWater();
brew(); // 抽象步骤,由子类实现
pourInCup();
addCondiments(); // 抽象步骤,由子类实现
}

// 基本步骤,不需要子类改变
void boilWater() {
std::cout << "Boiling water..." << std::endl;
}

void pourInCup() {
std::cout << "Pouring into cup..." << std::endl;
}

// 抽象步骤,由子类实现具体逻辑
virtual void brew() = 0;
virtual void addCondiments() = 0;

virtual ~Beverage() = default; // 虚析构函数
};

// 具体类:茶
class Tea : public Beverage {
public:
void brew() override {
std::cout << "Steeping the tea..." << std::endl;
}

void addCondiments() override {
std::cout << "Adding lemon..." << std::endl;
}
};

// 具体类:咖啡
class Coffee : public Beverage {
public:
void brew() override {
std::cout << "Dripping coffee through filter..." << std::endl;
}

void addCondiments() override {
std::cout << "Adding sugar and milk..." << std::endl;
}
};

// 主函数演示模板方法的使用
int main() {
Tea tea;
Coffee coffee;

std::cout << "Making tea:" << std::endl;
tea.prepareRecipe();

std::cout << "\nMaking coffee:" << std::endl;
coffee.prepareRecipe();

return 0;
}

2.策略模式

应用场景:在需要动态选择不同算法的场景,如有大量的if-else语句时,可以使用策略模式来进行优化。策略模式使不同的算法实现独立于使用它们的客户端进行管理和调用。

  • 策略接口:定义算法的公共接口。

  • 具体策略类:实现策略接口的不同算法。(对于同一个任务有不同的算法)

  • 上下文类:持有一个策略对象的引用,并在客户端需要时调用策略对象的算法。

计算支付金额的例子:

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

// 策略接口,定义算法接口
class PaymentStrategy {
public:
virtual ~PaymentStrategy() = default;
virtual void pay(int amount) const = 0; // 定义一个纯虚函数,具体策略类实现该方法
};

// 具体策略类:信用卡支付
class CreditCardPayment : public PaymentStrategy {
public:
void pay(int amount) const override {
std::cout << "Paid " << amount << " using Credit Card." << std::endl;
}
};

// 具体策略类:PayPal支付
class PayPalPayment : public PaymentStrategy {
public:
void pay(int amount) const override {
std::cout << "Paid " << amount << " using PayPal." << std::endl;
}
};

// 具体策略类:比特币支付
class BitcoinPayment : public PaymentStrategy {
public:
void pay(int amount) const override {
std::cout << "Paid " << amount << " using Bitcoin." << std::endl;
}
};

// 上下文类,使用策略进行支付
class PaymentContext {
private:
std::unique_ptr<PaymentStrategy> strategy; // 使用智能指针管理策略对象

public:
// 设置策略
void setStrategy(std::unique_ptr<PaymentStrategy> newStrategy) {
strategy = std::move(newStrategy);
}

// 执行支付
void executePayment(int amount) const {
if (strategy) {
strategy->pay(amount);
} else {
std::cout << "No payment strategy set!" << std::endl;
}
}
};

// 主函数演示策略模式的使用
int main() {
PaymentContext context;

// 使用信用卡支付
context.setStrategy(std::make_unique<CreditCardPayment>());
context.executePayment(100);

// 使用PayPal支付
context.setStrategy(std::make_unique<PayPalPayment>());
context.executePayment(200);

// 使用比特币支付
context.setStrategy(std::make_unique<BitcoinPayment>());
context.executePayment(300);

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
#include <iostream>
#include <vector>
#include <algorithm>

// 观察者基类
class Observer {
public:
virtual ~Observer() {}
virtual void update() = 0; // 定义一个纯虚函数,子类必须实现
};

// 主题类(被观察者)
class Subject {
private:
std::vector<Observer*> observers; // 保存观察者的列表

public:
void attach(Observer* observer) {
observers.push_back(observer);
}

void detach(Observer* observer) {
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}

void notify() {
for (Observer* observer : observers) {
observer->update();
}
}
};

// 具体观察者类
class ConcreteObserver : public Observer {
private:
std::string name;

public:
ConcreteObserver(const std::string& observerName) : name(observerName) {}

void update() override {
std::cout << "Observer " << name << " has been notified!" << std::endl;
}
};

// 主函数演示
int main() {
Subject subject;

// 创建具体观察者
ConcreteObserver observer1("Observer 1");
ConcreteObserver observer2("Observer 2");

// 将观察者附加到主题
subject.attach(&observer1);
subject.attach(&observer2);

// 通知所有观察者
std::cout << "Notifying observers..." << std::endl;
subject.notify();

// 移除一个观察者
subject.detach(&observer1);

// 再次通知剩余的观察者
std::cout << "Notifying observers after detaching one observer..." << std::endl;
subject.notify();

return 0;
}

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

// 组件接口,定义对象的基础操作
class Component {
public:
virtual ~Component() = default;
virtual void operation() const = 0; // 定义了一个纯虚函数
};

// 具体组件,实现了组件接口
class ConcreteComponent : public Component {
public:
void operation() const override {
std::cout << "Plain Text";
}
};

// 装饰器基类,继承自组件接口
class Decorator : public Component {
protected:
std::shared_ptr<Component> component; // 持有组件对象的引用

public:
Decorator(std::shared_ptr<Component> comp) : component(comp) {}
void operation() const override {
if (component) {
component->operation(); // 转发给被装饰的组件
}
}
};

// 具体装饰器:加粗文本
class BoldDecorator : public Decorator {
public:
BoldDecorator(std::shared_ptr<Component> comp) : Decorator(comp) {}
void operation() const override {
std::cout << "<b>";
Decorator::operation(); // 调用基础组件的操作
std::cout << "</b>";
}
};

// 具体装饰器:斜体文本
class ItalicDecorator : public Decorator {
public:
ItalicDecorator(std::shared_ptr<Component> comp) : Decorator(comp) {}
void operation() const override {
std::cout << "<i>";
Decorator::operation(); // 调用基础组件的操作
std::cout << "</i>";
}
};

// 主函数演示装饰模式的使用
int main() {
// 创建基础组件
std::shared_ptr<Component> text = std::make_shared<ConcreteComponent>();

// 将组件装饰为加粗文本
std::shared_ptr<Component> boldText = std::make_shared<BoldDecorator>(text);

// 将组件装饰为斜体和加粗文本
std::shared_ptr<Component> italicBoldText = std::make_shared<ItalicDecorator>(boldText);

// 输出结果
std::cout << "Decorated text: ";
italicBoldText->operation(); // 输出 <i><b>Plain Text</b></i>
std::cout << std::endl;

return 0;
}

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

// 实现接口(Implementor),定义绘制行为
class Color {
public:
virtual ~Color() = default;
virtual void applyColor() const = 0; // 纯虚函数,具体实现由子类提供
};

// 具体实现类:红色
class RedColor : public Color {
public:
void applyColor() const override {
std::cout << "Red";
}
};

// 具体实现类:蓝色
class BlueColor : public Color {
public:
void applyColor() const override {
std::cout << "Blue";
}
};

// 抽象类(Abstraction),定义形状
class Shape {
protected:
std::shared_ptr<Color> color; // 持有实现接口的引用

public:
Shape(std::shared_ptr<Color> col) : color(col) {}
virtual ~Shape() = default;
virtual void draw() const = 0; // 纯虚函数,具体实现由子类提供
};

// 扩展抽象类(RefinedAbstraction):圆形
class Circle : public Shape {
public:
Circle(std::shared_ptr<Color> col) : Shape(col) {}

void draw() const override {
std::cout << "Circle drawn in ";
color->applyColor(); // 使用实现接口的功能
std::cout << " color." << std::endl;
}
};

// 扩展抽象类(RefinedAbstraction):正方形
class Square : public Shape {
public:
Square(std::shared_ptr<Color> col) : Shape(col) {}

void draw() const override {
std::cout << "Square drawn in ";
color->applyColor(); // 使用实现接口的功能
std::cout << " color." << std::endl;
}
};

// 主函数演示桥模式的使用
int main() {
// 创建红色实现并绘制圆形
std::shared_ptr<Color> red = std::make_shared<RedColor>();
std::shared_ptr<Shape> redCircle = std::make_shared<Circle>(red);
redCircle->draw();

// 创建蓝色实现并绘制正方形
std::shared_ptr<Color> blue = std::make_shared<BlueColor>();
std::shared_ptr<Shape> blueSquare = std::make_shared<Square>(blue);
blueSquare->draw();

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

// 抽象产品(Product)
class Document {
public:
virtual void open() const = 0;
virtual ~Document() = default;
};

// 具体产品:文本文档(ConcreteProduct)
class TextDocument : public Document {
public:
void open() const override {
std::cout << "Opening a text document." << std::endl;
}
};

// 具体产品:图像文档(ConcreteProduct)
class ImageDocument : public Document {
public:
void open() const override {
std::cout << "Opening an image document." << std::endl;
}
};

// 抽象工厂(Creator)
class DocumentCreator {
public:
virtual std::unique_ptr<Document> createDocument() const = 0;
virtual ~DocumentCreator() = default;
};

// 具体工厂:文本文档工厂(ConcreteCreator)
class TextDocumentCreator : public DocumentCreator {
public:
std::unique_ptr<Document> createDocument() const override {
return std::make_unique<TextDocument>();
}
};

// 具体工厂:图像文档工厂(ConcreteCreator)
class ImageDocumentCreator : public DocumentCreator {
public:
std::unique_ptr<Document> createDocument() const override {
return std::make_unique<ImageDocument>();
}
};

// 客户端代码
void openDocument(const DocumentCreator& creator) {
std::unique_ptr<Document> doc = creator.createDocument();
doc->open();
}

int main() {
TextDocumentCreator textCreator;
ImageDocumentCreator imageCreator;

std::cout << "Using the text document creator:" << std::endl;
openDocument(textCreator);

std::cout << "\nUsing the image document creator:" << std::endl;
openDocument(imageCreator);

return 0;
}

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

// 抽象产品:按钮
class Button {
public:
virtual void paint() const = 0;
virtual ~Button() = default;
};

// 具体产品:Windows 按钮
class WindowsButton : public Button {
public:
void paint() const override {
std::cout << "Rendering a button in Windows style." << std::endl;
}
};

// 具体产品:macOS 按钮
class MacButton : public Button {
public:
void paint() const override {
std::cout << "Rendering a button in macOS style." << std::endl;
}
};

// 抽象产品:文本框
class TextBox {
public:
virtual void display() const = 0;
virtual ~TextBox() = default;
};

// 具体产品:Windows 文本框
class WindowsTextBox : public TextBox {
public:
void display() const override {
std::cout << "Displaying a text box in Windows style." << std::endl;
}
};

// 具体产品:macOS 文本框
class MacTextBox : public TextBox {
public:
void display() const override {
std::cout << "Displaying a text box in macOS style." << std::endl;
}
};

// 抽象工厂:GUI 工厂
class GUIFactory {
public:
virtual std::unique_ptr<Button> createButton() const = 0;
virtual std::unique_ptr<TextBox> createTextBox() const = 0;
virtual ~GUIFactory() = default;
};

// 具体工厂:Windows 工厂
class WindowsFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() const override {
return std::make_unique<WindowsButton>();
}
std::unique_ptr<TextBox> createTextBox() const override {
return std::make_unique<WindowsTextBox>();
}
};

// 具体工厂:macOS 工厂
class MacFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() const override {
return std::make_unique<MacButton>();
}
std::unique_ptr<TextBox> createTextBox() const override {
return std::make_unique<MacTextBox>();
}
};

// 客户端代码
void buildInterface(const GUIFactory& factory) {
auto button = factory.createButton();
auto textBox = factory.createTextBox();

button->paint();
textBox->display();
}

int main() {
WindowsFactory windowsFactory;
MacFactory macFactory;

std::cout << "Building Windows interface:" << std::endl;
buildInterface(windowsFactory);

std::cout << "\nBuilding macOS interface:" << std::endl;
buildInterface(macFactory);

return 0;
}

8.原型模式

通过复制现有对象来创建新的对象,而不是通过实例化类来创建。

模式结构:

  • 抽象原型:定义一个接口,用于复制自身。

  • 具体原型:实现复制自身的方法。

  • 客户端:通过调用原型对象的 clone 方法来创建新的对象。

示例:

一个简单的图形编辑器,需要频繁创建和复制不同类型的图形(如圆形和矩形)。在未使用原型模式的情况下,要会使用 new 关键字手动创建对象。使用原型模式后,可以更灵活地通过克隆已有对象来创建新对象。

没有使用原型模式的实现:

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

// 图形基类
class Shape {
public:
virtual void draw() const = 0;
virtual ~Shape() = default;
};

// 具体图形:圆形
class Circle : public Shape {
private:
int radius;
public:
Circle(int r) : radius(r) {}

void draw() const override {
std::cout << "Drawing a circle with radius: " << radius << std::endl;
}
};

// 具体图形:矩形
class Rectangle : public Shape {
private:
int width, height;
public:
Rectangle(int w, int h) : width(w), height(h) {}

void draw() const override {
std::cout << "Drawing a rectangle with width: " << width << " and height: " << height << std::endl;
}
};

// 客户端代码,手动创建对象
int main() {
std::unique_ptr<Shape> shape1 = std::make_unique<Circle>(5);
std::unique_ptr<Shape> shape2 = std::make_unique<Rectangle>(4, 6);

shape1->draw();
shape2->draw();

// 想要复制时,需要手动创建
std::unique_ptr<Shape> anotherCircle = std::make_unique<Circle>(5);
anotherCircle->draw();

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

// 抽象原型类
class Shape {
public:
virtual void draw() const = 0;
virtual std::unique_ptr<Shape> clone() const = 0; // 克隆方法
virtual ~Shape() = default;
};

// 具体原型:圆形
class Circle : public Shape {
private:
int radius;
public:
Circle(int r) : radius(r) {}

void draw() const override {
std::cout << "Drawing a circle with radius: " << radius << std::endl;
}

std::unique_ptr<Shape> clone() const override {
return std::make_unique<Circle>(*this); // 使用复制构造函数
}
};

// 具体原型:矩形
class Rectangle : public Shape {
private:
int width, height;
public:
Rectangle(int w, int h) : width(w), height(h) {}

void draw() const override {
std::cout << "Drawing a rectangle with width: " << width << " and height: " << height << std::endl;
}

std::unique_ptr<Shape> clone() const override {
return std::make_unique<Rectangle>(*this); // 使用复制构造函数
}
};

// 客户端代码,通过克隆创建对象
int main() {
std::unique_ptr<Shape> originalCircle = std::make_unique<Circle>(5);
std::unique_ptr<Shape> originalRectangle = std::make_unique<Rectangle>(4, 6);

originalCircle->draw();
originalRectangle->draw();

// 使用原型克隆对象
std::unique_ptr<Shape> clonedCircle = originalCircle->clone();
std::unique_ptr<Shape> clonedRectangle = originalRectangle->clone();

clonedCircle->draw();
clonedRectangle->draw();

return 0;
}

9.构建器模式

应用场景:适用于构建复杂对象,特别是当对象包含多个可选或可变部分时。

结构:

  • 产品类:需要构建的复杂对象。
  • 构建器接口:定义构建产品各个部分的方法
  • 具体构建器:实现 Builder 接口并提供构建产品的方法(可扩展的具体实现,与产品类用组合代替继承)
  • 指挥者:使用 Builder 来控制构建过程的顺序(步骤,可扩展)
  • 客户端:创建 BuilderDirector,并启动构建过程。
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
#include <iostream>
#include <memory>
#include <string>

// 产品类
class Car {
public:
std::string engine;
std::string wheels;
std::string body;

void showCar() const {
std::cout << "Car with engine: " << engine << ", wheels: " << wheels << ", body: " << body << std::endl;
}
};

// 抽象构建器类
class CarBuilder {
public:
virtual ~CarBuilder() = default;
virtual void buildEngine() = 0;
virtual void buildWheels() = 0;
virtual void buildBody() = 0;
virtual std::shared_ptr<Car> getCar() = 0;
};

// 具体构建器类
class SportsCarBuilder : public CarBuilder {
private:
std::shared_ptr<Car> car;
public:
SportsCarBuilder() {
car = std::make_shared<Car>();
}

void buildEngine() override {
car->engine = "V8 Engine";
}

void buildWheels() override {
car->wheels = "Sports Wheels";
}

void buildBody() override {
car->body = "Sleek Sports Body";
}

std::shared_ptr<Car> getCar() override {
return car;
}
};

// 指挥者类
class Director {
public:
void construct(std::shared_ptr<CarBuilder> builder) {
builder->buildEngine();
builder->buildWheels();
builder->buildBody();
}
};

// 客户端代码
int main() {
std::shared_ptr<CarBuilder> sportsCarBuilder = std::make_shared<SportsCarBuilder>();
Director director;
director.construct(sportsCarBuilder);

std::shared_ptr<Car> car = sportsCarBuilder->getCar();
car->showCar(); // 输出:Car with engine: V8 Engine, wheels: Sports Wheels, body: Sleek Sports Body

return 0;
}

10.单例模式

应用场景:确保某个类只有一个实例,并提供一个全局访问点来访问该实例。常用于需要控制全局访问、限制资源或共享资源的场景。用于减少创建对象的数量

特点:

  • 唯一性:保证一个类只有一个实例。
  • 全局访问点:提供对该实例的全局访问。
  • 延迟实例化:实例化通常是在首次访问时才创建,节省资源。
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
#include <iostream>
#include <string>
#include <memory>

class Logger {
private:
// 私有构造函数,防止外部实例化
Logger() {
std::cout << "Logger created" << std::endl;
}

// 禁用拷贝构造函数和赋值运算符,防止拷贝
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;

public:
// 提供全局访问点的静态方法
static Logger& getInstance() {
static Logger instance; // 静态本地变量,保证只创建一次
return instance;
}

void log(const std::string& message) {
std::cout << "Log: " << message << std::endl;
}
};

int main() {
// 通过 getInstance() 获取唯一的实例
Logger& logger1 = Logger::getInstance();
Logger& logger2 = Logger::getInstance();

logger1.log("This is the first message");
logger2.log("This is the second message");

// 输出验证是否为同一实例
if (&logger1 == &logger2) {
std::cout << "Both loggers are the same instance" << std::endl;
}

return 0;
}

注1:私有构造函数防止类的外部创建实例。

注2:通过删除拷贝构造函数和赋值运算符,防止实例被复制。

注3:static 变量 instance 保证实例只创建一次,并在程序结束时自动销毁。:

11.享元模式

应用场景:用于减少创建对象的数量,从而减少内存消耗并提高性能。常用于系统中需要大量细粒度对象的场景,比如图形编辑器中的图元或文字处理器中的字符。

共享的部分做成员,外部状态做参数,调用时提供

特点:

  • 共享:将对象的共享部分提取出来,通过共享减少内存开销。
  • 分离状态:对象可以分为内部状态和外部状态。内部状态是共享的,外部状态是每个对象特有的,不会被共享。
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
#include <iostream>
#include <unordered_map>
#include <memory>

class Circle {
private:
std::string color; // 共享的内部状态

public:
Circle(const std::string& col) : color(col) {}

// 绘制时传递外部状态作为参数
void draw(int x, int y, int radius) const {
std::cout << "Circle: Color=" << color << ", x=" << x << ", y=" << y << ", radius=" << radius << std::endl;
}
};

class CircleFactory {
private:
std::unordered_map<std::string, std::shared_ptr<Circle>> circleMap;

public:
std::shared_ptr<Circle> getCircle(const std::string& color) {
auto it = circleMap.find(color);
if (it != circleMap.end()) {
return it->second;
}

auto newCircle = std::make_shared<Circle>(color);
circleMap[color] = newCircle;
std::cout << "Creating circle of color: " << color << std::endl;
return newCircle;
}
};

int main() {
CircleFactory circleFactory;

auto circle1 = circleFactory.getCircle("Red");
circle1->draw(10, 10, 5); // 使用外部状态
circle1->draw(20, 20, 10); // 传递不同的外部状态

auto circle2 = circleFactory.getCircle("Red");
circle2->draw(30, 30, 15); // 共享颜色,外部状态不同

auto circle3 = circleFactory.getCircle("Green");
circle3->draw(15, 15, 7);

return 0;
}

注:

  • 共享部分:颜色信息在 Circle 类中存储和共享。

  • 外部状态xyradius 作为参数传递给 draw() 方法,每个调用时提供不同的值,不共享。

12.面门模式

应用场景:为子系统中的一组复杂接口提供一个统一的接口,使得子系统更容易使用。适用于简化接口调用

客户端-》面门类-》子系统类

注:客户端不需要直接依赖子系统的具体实现,而是依赖门面接口,降低了耦合性。

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

// 子系统类
class AudioPlayer {
public:
void playAudio() {
std::cout << "Playing audio..." << std::endl;
}
};

class VideoPlayer {
public:
void playVideo() {
std::cout << "Playing video..." << std::endl;
}
};

class Subtitles {
public:
void loadSubtitles() {
std::cout << "Loading subtitles..." << std::endl;
}
};

// 门面类
class MediaFacade {
private:
std::unique_ptr<AudioPlayer> audioPlayer;
std::unique_ptr<VideoPlayer> videoPlayer;
std::unique_ptr<Subtitles> subtitles;

public:
MediaFacade() {
audioPlayer = std::make_unique<AudioPlayer>();
videoPlayer = std::make_unique<VideoPlayer>();
subtitles = std::make_unique<Subtitles>();
}

void playMedia() {
audioPlayer->playAudio();
videoPlayer->playVideo();
subtitles->loadSubtitles();
}
};

int main() {
// 客户端使用门面类进行简化调用
MediaFacade mediaFacade;
mediaFacade.playMedia();
return 0;
}

13.代理模式

应用场景:用于为另一个对象提供一种“代理”或占位符以控制对这个对象的访问。例如延迟加载、控制访问权限、日志记录等。

例:使用虚代理来实现按需加载图像资源

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
#include <iostream>
#include <string>
#include <memory>

class Image {
public:
virtual void display() const = 0;
virtual ~Image() = default;
};

class RealImage : public Image {
public:
RealImage(const std::string& fileName) : fileName(fileName) {
loadImage();
}

void display() const override {
std::cout << "Displaying image: " << fileName << std::endl;
}

private:
std::string fileName;

void loadImage() {
std::cout << "Loading image from " << fileName << "..." << std::endl;
}
};

class ProxyImage : public Image {
public:
ProxyImage(const std::string& fileName) : fileName(fileName), realImage(nullptr) {}

void display() const override {
if (!realImage) {
realImage = std::make_unique<RealImage>(fileName); // 延迟加载图像
}
realImage->display();
}

private:
std::string fileName;
mutable std::unique_ptr<RealImage> realImage;
};

int main() {
// 创建代理对象,不会立即加载图像
std::unique_ptr<Image> image = std::make_unique<ProxyImage>("photo.jpg");
std::cout << "Image created, but not loaded yet." << std::endl;

// 当需要时才加载并显示图像
image->display();

return 0;
}

14.适配器模式

应用场景:适配器模式主要解决接口不匹配的问题。

组成:

  • 目标接口:客户端期望的接口。
  • 需要适配的类:拥有不兼容接口的类。
  • 适配器:将目标接口与需要适配的类进行连接,转换接口以满足客户端需求。
  • 客户端:通过目标接口与适配器交互。
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
#include <iostream>
#include <string>
#include <memory>
//被适配类
class OldPrinter {
public:
void oldPrint(const std::string& text) {
std::cout << "Old Printer: " << text << std::endl;
}
};

class NewPrinterInterface {
public:
virtual void print(const std::string& text) = 0;
virtual ~NewPrinterInterface() = default;
};

// 对象适配器:通过组合实现
class PrinterAdapter : public NewPrinterInterface {
private:
std::shared_ptr<OldPrinter> oldPrinter;

public:
PrinterAdapter(std::shared_ptr<OldPrinter> oldPrinter) : oldPrinter(oldPrinter) {}

void print(const std::string& text) override {
oldPrinter->oldPrint(text); // 调用 OldPrinter 的 oldPrint 方法
}
};

int main() {
auto oldPrinter = std::make_shared<OldPrinter>();
PrinterAdapter adapter(oldPrinter);
adapter.print("Hello, World!");
return 0;
}

15.中介者模式

应用场景:用于减少多个对象之间的直接相互依赖。通过引入一个中介者对象,所有对象之间的通信都通过中介者完成,降低了对象之间的耦合性。

未使用中介者模式:

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

class User {
private:
std::string name;

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

void sendMessage(User& receiver, const std::string& message) {
std::cout << name << " to " << receiver.getName() << ": " << message << std::endl;
}

std::string getName() const {
return name;
}
};

int main() {
User user1("Alice");
User user2("Bob");

user1.sendMessage(user2, "Hello, Bob!");
user2.sendMessage(user1, "Hi, Alice!");

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
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
#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 中介者接口
class ChatMediator {
public:
virtual void sendMessage(const std::string& message, class User* sender, const std::string& receiverName) = 0;
virtual void addUser(std::shared_ptr<class User> user) = 0;
virtual ~ChatMediator() = default;
};

// 用户类
class User {
protected:
std::string name;
ChatMediator* mediator;

public:
User(const std::string& name, ChatMediator* mediator) : name(name), mediator(mediator) {}

virtual void send(const std::string& message, const std::string& receiverName) {
mediator->sendMessage(message, this, receiverName); // 通过中介者发送消息
}

virtual void receive(const std::string& message, const std::string& senderName) {
std::cout << name << " received from " << senderName << ": " << message << std::endl;
}

std::string getName() const {
return name;
}
};

// 具体中介者
class ConcreteChatMediator : public ChatMediator {
private:
std::vector<std::shared_ptr<User>> users;

public:
void addUser(std::shared_ptr<User> user) override {
users.push_back(user);
}

void sendMessage(const std::string& message, User* sender, const std::string& receiverName) override {
for (const auto& user : users) {
if (user->getName() == receiverName) { // 找到目标用户
user->receive(message, sender->getName());
return;
}
}
std::cout << "User " << receiverName << " not found!" << std::endl;
}
};

// 测试
int main() {
ConcreteChatMediator mediator;

auto user1 = std::make_shared<User>("Alice", &mediator);
auto user2 = std::make_shared<User>("Bob", &mediator);
auto user3 = std::make_shared<User>("Charlie", &mediator);
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
// A 向 B 发送消息
user1->send("Hello Bob!", "Bob");
// C 向 A 发送消息
user3->send("Hi Alice!", "Alice");
// A 向不存在的用户发送消息
user1->send("Hello David!", "David");
return 0;
}

16.状态模式

应用场景:对象的行为由对象的状态所决定,而通过使用状态模式实现了状态和行为的分离。

实现行为固定时,对状态的扩展

示例:

电梯有以下状态:

  • 运行中(Moving)
  • 停止中(Stopped)
  • 开门(Open)
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
#include <iostream>
#include <memory>
#include <string>

// 抽象状态类
class State {
public:
//行为:
virtual void openDoor() = 0;
virtual void closeDoor() = 0;
virtual void move() = 0;
virtual void stop() = 0;
virtual ~State() = default;
};

// 前向声明上下文类(为状态类使用)
class Elevator;

// 具体状态类:停止中
class StoppedState : public State {
private:
Elevator* elevator;

public:
explicit StoppedState(Elevator* elevator) : elevator(elevator) {}

void openDoor() override;
void closeDoor() override;
void move() override;
void stop() override;
};

// 具体状态类:运行中
class MovingState : public State {
private:
Elevator* elevator;

public:
explicit MovingState(Elevator* elevator) : elevator(elevator) {}//使用原始指针防止循环引用

void openDoor() override;
void closeDoor() override;
void move() override;
void stop() override;
};

// 具体状态类:开门
class OpenState : public State {
private:
Elevator* elevator;

public:
explicit OpenState(Elevator* elevator) : elevator(elevator) {}

void openDoor() override;
void closeDoor() override;
void move() override;
void stop() override;
};

// 上下文类:电梯
class Elevator {
private:
std::shared_ptr<State> currentState;

public:
explicit Elevator(std::shared_ptr<State> initialState) : currentState(std::move(initialState)) {}

void setState(std::shared_ptr<State> state) {
currentState = std::move(state);
}

void openDoor() {
currentState->openDoor();
}

void closeDoor() {
currentState->closeDoor();
}

void move() {
currentState->move();
}

void stop() {
currentState->stop();
}
};

// 实现具体状态类的方法
void StoppedState::openDoor() {
std::cout << "Opening door...\n";
elevator->setState(std::make_shared<OpenState>(elevator));
}

void StoppedState::closeDoor() {
std::cout << "Door is already closed.\n";
}

void StoppedState::move() {
std::cout << "Elevator is starting to move...\n";
elevator->setState(std::make_shared<MovingState>(elevator));
}

void StoppedState::stop() {
std::cout << "Elevator is already stopped.\n";
}

void MovingState::openDoor() {
std::cout << "Cannot open door while moving.\n";
}

void MovingState::closeDoor() {
std::cout << "Door is already closed.\n";
}

void MovingState::move() {
std::cout << "Elevator is already moving.\n";
}

void MovingState::stop() {
std::cout << "Elevator is stopping...\n";
elevator->setState(std::make_shared<StoppedState>(elevator));
}

void OpenState::openDoor() {
std::cout << "Door is already open.\n";
}

void OpenState::closeDoor() {
std::cout << "Closing door...\n";
elevator->setState(std::make_shared<StoppedState>(elevator));
}

void OpenState::move() {
std::cout << "Cannot move with door open.\n";
}

void OpenState::stop() {
std::cout << "Elevator is already stopped.\n";
}

// 测试代码
int main() {
// 延迟初始化 Elevator 和 StoppedState,避免使用未初始化对象
auto elevator = std::make_shared<Elevator>(nullptr);
auto initialState = std::make_shared<StoppedState>(elevator.get());
elevator->setState(initialState);

elevator->openDoor(); // Opening door...
elevator->closeDoor(); // Closing door...
elevator->move(); // Elevator is starting to move...
elevator->stop(); // Elevator is stopping...
elevator->openDoor(); // Opening door...

return 0;
}

17.备忘录模式

应用场景:允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态(如浏览器回退、编辑器撤销)

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

// 备忘录类
class Memento {
private:
std::string state;

public:
explicit Memento(const std::string& state) : state(state) {}

std::string getState() const {
return state;
}
};

// 发起者类
class TextEditor {
private:
std::string text;

public:
void type(const std::string& newText) {
text += newText;
}

void showContent() const {
std::cout << "Current Content: " << text << std::endl;
}

// 创建备忘录
Memento save() const {
return Memento(text);
}

// 从备忘录恢复
void restore(const Memento& memento) {
text = memento.getState();
}
};

// 管理者类:进行保存备份副本、回档
class Caretaker {
private:
std::vector<Memento> history;

public:
void save(const Memento& memento) {
history.push_back(memento);
}

Memento get(int index) const {
if (index < 0 || index >= history.size()) {
throw std::out_of_range("Invalid index");
}
return history[index];
}
};

int main() {
TextEditor editor;
Caretaker caretaker;

editor.type("Hello, ");
caretaker.save(editor.save()); // 保存状态

editor.type("World!");
caretaker.save(editor.save()); // 保存状态

editor.type(" New content.");
editor.showContent();

// 恢复到上一个状态
editor.restore(caretaker.get(1));
editor.showContent();

// 恢复到初始状态
editor.restore(caretaker.get(0));
editor.showContent();

return 0;
}

18.组合模式

组合模式将对象组合成树形结构,来一致地处理单个对象和对象的组合。

结构:

  • Component(抽象组件):定义了对象的公共接口,包括对组合对象的常见操作
  • Leaf(叶子节点):表示树形结构的最小单元,不包含子节点。
  • Composite(组合节点):包含子节点的容器,可以是LeafComposite,实现管理子节点的操作,例如添加、移除和遍历子节点。
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
#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 抽象组件类
class FileSystemComponent {
public:
virtual void display(int depth = 0) const = 0; // 显示组件内容
virtual ~FileSystemComponent() = default;
};

// 叶子节点类:文件
class File : public FileSystemComponent {
private:
std::string name;

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

void display(int depth = 0) const override {
std::cout << std::string(depth, '-') << "File: " << name << std::endl;
}
};

// 组合节点类:文件夹
class Folder : public FileSystemComponent {
private:
std::string name;
std::vector<std::shared_ptr<FileSystemComponent>> children;

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

void add(std::shared_ptr<FileSystemComponent> component) {
children.push_back(component);
}

void display(int depth = 0) const override {
std::cout << std::string(depth, '-') << "Folder: " << name << std::endl;
for (const auto& child : children) {
child->display(depth + 2); // 递归调用子节点的 display 方法
}
}
};

// 测试代码
int main() {
auto file1 = std::make_shared<File>("file1.txt");
auto file2 = std::make_shared<File>("file2.txt");

auto subFolder = std::make_shared<Folder>("SubFolder");
subFolder->add(file1);

auto mainFolder = std::make_shared<Folder>("MainFolder");
mainFolder->add(subFolder);
mainFolder->add(file2);

mainFolder->display();

return 0;
}