设计模式入门
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 90 课,共 104 课。
设计模式是经过验证、可重复使用的解决方案,用于解决软件设计中常见的问题。它们不是可以直接复制的代码,而是描述如何构建类和对象以优雅地解决特定挑战的模板或蓝图。
这个概念由“四人帮”(GoF)在他们 1994 年出版的书中推广开来。该书整理了 23 种基础模式。这些模式通常分为三类:
| 类别 | 用途 | 示例 |
|---|---|---|
| 创建型 | 对象创建机制 | Singleton、Factory、Builder |
| 结构型 | 类和对象的组合 | Adapter、Decorator、Composite |
| 行为型 | 对象交互和职责 | Observer、Strategy、Command |
为什么要学习设计模式?设计模式为开发者提供了共同的词汇,说“这里使用 Factory”就能立即传达一个复杂的想法。它们还能帮你避免重复造轮子,让代码更灵活、更易维护。
在 C++ 中,设计模式会利用你已经学过的面向对象编程特性:继承、多态、抽象类和模板。在接下来的几节课中,你将实现几种重要的设计模式,并了解每种模式适用于什么场景。
挑战
简单让我们来构建一个简单的模式分类器,展示你对三种设计模式类别的理解。你将创建一个系统,输入模式名称后,判断它属于哪种类别:Creational、Structural 或 Behavioral,并简要说明该类别的用途。
你需要将代码分散到三个文件中:
PatternCategory.h:定义一个名为PatternCategory的抽象基类,用来表示一种设计模式类别。它应包含:- 一个纯虚方法
getName(),以字符串形式返回类别名称 - 一个纯虚方法
getPurpose(),返回对该类别中模式用途的描述 - 一个虚析构函数
然后,创建三个继承自
PatternCategory的派生类:CreationalCategory:返回名称"Creational",用途为"Object creation mechanisms"StructuralCategory:返回名称"Structural",用途为"Class and object composition"BehavioralCategory:返回名称"Behavioral",用途为"Object interaction and responsibility"
- 一个纯虚方法
PatternClassifier.h:创建一个PatternClassifier类,用来判断给定模式所属的类别。你的分类器应包含一个
classify方法,接收模式名称(字符串),并返回指向相应PatternCategory的指针。使用智能指针(std::unique_ptr)管理内存。分类器应识别以下模式:
- Creational:
Singleton、Factory、Builder - Structural:
Adapter、Decorator、Composite - Behavioral:
Observer、Strategy、Command
如果无法识别模式名称,则返回
nullptr。- Creational:
main.cpp:读取一个输入,即设计模式的名称。创建一个
PatternClassifier,并用它对输入的模式进行分类。如果模式能够识别,则打印:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]如果无法识别该模式,则打印:
Unknown pattern: [PatternName]
例如,输入 Singleton 时:
Singleton is a Creational pattern
Purpose: Object creation mechanisms输入 Observer 时:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibility输入 Proxy 时:
Unknown pattern: Proxy这个挑战将巩固你对三种设计模式类别的理解,同时让你练习继承、多态和智能指针,这些概念你都已经掌握。多文件结构也体现了真实项目组织相关类的方式。
亲手试试
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// 读取模式名称
std::string patternName;
std::cin >> patternName;
// TODO:创建一个 PatternClassifier 实例
// TODO:使用分类器对输入的模式进行分类
// TODO:如果模式被识别,输出:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO:如果模式未被识别(nullptr),输出:
// "Unknown pattern: [PatternName]"
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器