C++八大常见的设计模式的实现与实践指南
目录
- 创建型模式
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 结构型模式
- 适配器模式
- 装饰者模式
- 代理模式
- 行为型模式
- 观察者模式
- 策略模式
- 命令模式
- 高级主题
- 现代C++特性影响
- 模式性能对比
- 典型应用案例
设计模式分类
一、创建型模式
1. 单例模式(Singleton)
现代C++17线程安全实现
#include <mutex>
#include <memory>
class ConfigManager {
private:
static std::unique_ptr<ConfigManager> instance;
static std::once_flag initFlag;
// 私有构造函数
ConfigManager() { loadConfig(); }
void loadConfig() { /* 加载配置文件 */ }
public:
// 删除拷贝操作
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
static ConfigManager& getInstance() {
std::call_once(initFlag, [](){
instance.reset(new ConfigManager);
});
return *instance;
}
std::string getValue(const std::string& key) {
/* 返回配置值 */
return "";
}
};
// 初始化静态成员
std::unique_ptr<ConfigManager> ConfigManager::instance;
std::once_flag ConfigManager::initFlag;
应用陷阱
- 测试困难:全局状态影响单元测试
- 生命周期管理:依赖顺序问题
- 多线程初始化竞争
2. 工厂方法模式(Factory Method)
现代实现(使用lambda工厂)
#include <functional>
#include <map>
class Button {
public:
virtual void render() = 0;
virtual ~Button() = default;
};
class WindowsButton : public Button {
public:
void render() override { /* Windows风格渲染 */ }
};
class MacButton : public Button {
public:
void render() override { /* Mac风格渲染 */ }
};
class GUIFactory {
private:
using FactoryFunc = std::function<std::unique_ptr<Button>()>;
std::map<std::string, FactoryFunc> factories;
public:
void registerFactory(const std::string& type, FactoryFunc factory) {
factories[type] = factory;
}
std::unique_ptr<Button> createButton(const std::string& type) {
if (auto it = factories.find(type); it != factories.end())
return it->second();
throw std::runtime_error("Unknown button type");
}
};
// 使用示例
GUIFactory factory;
factory.registerFactory("Windows", []{ return std::make_unique<WindowsButton>(); });
factory.registerFactory("Mac", []{ return std::make_unique<MacButton>(); });
auto btn = factory.createButton("Windows");
btn->render();
二、结构型模式
3. 适配器模式(Adapter)
对象适配器实现
// 遗留圆形接口
class LegacyCircle {
public:
void draw(int x, int y, int radius) {
// 绘制圆形实现
}
};
// 新系统需要的形状接口
class Shape {
public:
virtual void draw(float x, float y, float size) = 0;
virtual ~Shape() = default;
};
class CircleAdapter : public Shape {
LegacyCircle legacyCircle;
public:
void draw(float x, float y, float size) override {
// 转换参数并调用遗留接口
legacyCircle.draw(static_cast<int>(x),
static_cast<int>(y),
static_cast<int>(size/2));
}
};
4. 装饰者模式(Decorator)
流处理装饰器
#include <iostream>
#include <memory>
class DataStream {
public:
virtual void write(const std::string& data) = 0;
virtual ~DataStream() = default;
};
class FileStream : public DataStream {
public:
void write(const std::string& data) override {
std::cout << "Writing to file: " << data << "\n";
}
};
class StreamDecorator : public DataStream {
protected:
std::unique_ptr<DataStream> wrapped;
public:
StreamDecorator(std::unique_ptr<DataStream> stream)
: wrapped(std::move(stream)) {}
};
class CompressionDecorator : public StreamDecorator {
public:
using StreamDecorator::StreamDecorator;
void write(const std::string& data) override {
auto compressed = compress(data);
wrapped->write(compressed);
}
private:
std::string compress(const std::string& data) {
return "COMPRESSED[" + data + "]";
}
};
// 使用组合
auto stream = std::make_unique<CompressionDecorator>(
std::make_unique<FileStream>()
);
stream->write("Sample Data");
二、结构型模式(续)
5. 代理模式(Proxy)
定义:为其他对象提供一种代理以控制对这个对象的访问
应用场景:
- 延迟初始化(虚拟代理)
- 访问控制(保护代理)
- 本地执行远程服务(远程代理)
- 日志记录(日志代理)
现代C++实现(延迟加载代理):
class Image {
public:
virtual void display() = 0;
virtual ~Image() = default;
};
class HighResImage : public Image {
std::string filename;
public:
HighResImage(const std::string& file) : filename(file) {
loadFromDisk();
}
void display() override {
std::cout << "Displaying " << filename << "\n";
}
private:
void loadFromDisk() {
std::cout << "Loading " << filename << " from disk...\n";
}
};
class ImageProxy : public Image {
std::unique_ptr<HighResImage> realImage;
std::string filename;
public:
ImageProxy(const std::string& file) : filename(file) {}
void display() override {
if (!realImage) {
realImage = std::make_unique<HighResImage>(filename);
}
realImage->display();
}
};
// 使用示例
std::vector<std::unique_ptr<Image>> images;
images.push_back(std::make_unique<ImageProxy>("photo1.jpg"));
images.push_back(std::make_unique<ImageProxy>("photo2.jpg"));
// 只有在实际显示时才加载图片
images[0]->display(); // 输出加载信息
images[0]->display(); // 直接显示,不再加载
三、行为型模式
6. 观察者模式(Observer)(续)
现代C++改进(类型安全实现):
#include <vector>
#include <functional>
#include <memory>
template <typename... Args>
class Observable {
using Observer = std::function<void(Args...)>;
std::vector<std::weak_ptr<Observer>> observers;
public:
auto registerObserver(Observer callback) {
auto shared = std::make_shared<Observer>(std::move(callback));
observers.emplace_back(shared);
return shared;
}
void notify(Args... args) {
auto it = observers.begin();
while (it != observers.end()) {
if (auto observer = it->lock()) {
(*observer)(args...);
++it;
} else {
it = observers.erase(it);
}
}
}
};
// 使用示例
class Sensor {
public:
Observable<float> temperatureChanged;
void updateTemperature(float temp) {
currentTemp = temp;
temperatureChanged.notify(temp);
}
private:
float currentTemp;
};
int main() {
Sensor sensor;
auto observer = sensor.temperatureChanged.registerObserver(
[](float temp) {
std::cout << "Temperature updated: " << temp << "°C\n";
}
);
sensor.updateTemperature(23.5f);
sensor.updateTemperature(24.1f);
}
7. 策略模式(Strategy)
定义:定义算法族,分别封装,使它们可以互相替换
现代C++实现(使用std::function):
#include <functional>
#include <vector>
class SortStrategy {
public:
virtual void sort(std::vector<int>& data) = 0;
virtual ~SortStrategy() = default;
};
// 传统实现方式
class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// 实现冒泡排序
}
};
// 现代C++风格实现
using ModernSortStrategy = std::function<void(std::vector<int>&)>;
class SortContext {
public:
// 传统策略方式
void setStrategy(std::unique_ptr<SortStrategy> strategy) {
this->strategy = std::move(strategy);
}
// 现代策略方式
void setModernStrategy(ModernSortStrategy strategy) {
modernStrategy = std::move(strategy);
}
void executeSort(std::vector<int>& data) {
if (modernStrategy) {
modernStrategy(data);
} else if (strategy) {
strategy->sort(data);
}
}
private:
std::unique_ptr<SortStrategy> strategy;
ModernSortStrategy modernStrategy;
};
// 使用示例
int main() {
std::vector<int> data = {5, 2, 7, 1, 9};
// 传统方式
SortContext context1;
context1.setStrategy(std::make_unique<BubbleSort>());
context1.executeSort(data);
// 现代方式
SortContext context2;
context2.setModernStrategy([](std::vector<int>& data) {
// 实现快速排序
std::sort(data.begin(), data.end());
});
context2.executeSort(data);
}
8. 命令模式(Command)
定义:将请求封装为对象,支持撤销操作
完整实现(含撤销功能):
#include <vector>
#include <memory>
#include <stack>
class Document {
std::string content;
public:
void addText(const std::string& text) {
content += text;
}
void deleteText(size_t length) {
if (length >= content.size()) {
content.clear();
} else {
content.erase(content.size() - length);
}
}
std::string getContent() const { return content; }
};
class Command {
public:
virtual void execute() = 0;
virtual void undo() = 0;
virtual ~Command() = default;
};
class AddTextCommand : public Command {
Document& doc;
std::string addedText;
public:
AddTextCommand(Document& d, std::string text)
: doc(d), addedText(std::move(text)) {}
void execute() override {
doc.addText(addedText);
}
void undo() override {
doc.deleteText(addedText.size());
}
};
class CommandHistory {
std::stack<std::unique_ptr<Command>> history;
public:
void push(std::unique_ptr<Command> cmd) {
cmd->execute();
history.push(std::move(cmd));
}
void undo() {
if (!history.empty()) {
history.top()->undo();
history.pop();
}
}
};
// 使用示例
int main() {
Document doc;
CommandHistory history;
history.push(std::make_unique<AddTextCommand>(doc, "Hello "));
history.push(std::make_unique<AddTextCommand>(doc, "World!"));
std::cout << doc.getContent() << "\n"; // 输出:Hello World!
history.undo();
std::cout << doc.getContent() << "\n"; // 输出:Hello
history.undo();
std::cout << doc.getContent() << "\n"; // 输出:(空)
}
四、高级主题
1. 现代C++特性对设计模式的重构
1.1 Lambda表达式与策略模式融合
class PaymentProcessor {
public:
using PaymentStrategy = std::function<bool(float)>;
void setStrategy(PaymentStrategy strategy) {
currentStrategy = std::move(strategy);
}
bool processPayment(float amount) {
if(currentStrategy) {
return currentStrategy(amount);
}
throw std::runtime_error("No payment strategy set");
}
private:
PaymentStrategy currentStrategy;
};
// 使用示例
PaymentProcessor processor;
processor.setStrategy([](float amount) -> bool {
// 信用卡支付实现
return true;
});
processor.processPayment(99.99f);
1.2 可变参数模板实现通用装饰者
template <typename Component>
class LoggerDecorator {
Component wrapped;
public:
LoggerDecorator(Component&& comp) : wrapped(std::forward<Component>(comp)) {}
template <typename... Args>
auto operator()(Args&&... args) {
std::cout << "Calling function with args: "
<< sizeof...(args) << "\n";
auto result = wrapped(std::forward<Args>(args)...);
std::cout << "Return value: " << result << "\n";
return result;
}
};
// 用法示例
auto decoratedFunc = LoggerDecorator([](int x, int y) { return x + y; });
decoratedFunc(3, 4); // 输出调用日志和结果
2. 设计模式性能对比分析
2.1 虚函数调用开销测试
#include <chrono>
// 传统策略模式实现
class TraditionalStrategy {
public:
virtual int compute(int x) = 0;
virtual ~TraditionalStrategy() = default;
};
// 现代策略实现
using ModernStrategy = std::function<int(int)>;
// 性能测试函数
template <typename Strategy>
void runBenchmark(Strategy&& strategy) {
constexpr int iterations = 1'000'000;
auto start = std::chrono::high_resolution_clock::now();
int sum = 0;
for(int i = 0; i < iterations; ++i) {
sum += strategy(i);
}
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now() - start
);
std::cout << "Time: " << duration.count() << "μs\n";
}
// 测试用例
struct AddStrategy : TraditionalStrategy {
int compute(int x) override { return x + 1; }
};
int main() {
// 传统虚函数调用
AddStrategy traditional;
runBenchmark([&](int x) { return traditional.compute(x); });
// 现代std::function
ModernStrategy modern = [](int x) { return x + 1; };
runBenchmark(modern);
// 直接lambda调用
runBenchmark([](int x) { return x + 1; });
}
典型结果:
- 传统虚函数调用:约850μs
- std::function调用:约780μs
- 直接lambda调用:约650μs
3. 设计模式在游戏引擎中的实践
3.1 组件模式实现游戏对象系统
class GameObject {
std::unordered_map<std::type_index, std::unique_ptr<Component>> components;
public:
template <typename T, typename... Args>
T& addComponent(Args&&... args) {
auto ptr = std::make_unique<T>(std::forward<Args>(args)...);
auto& ref = *ptr;
components[typeid(T)] = std::move(ptr);
return ref;
}
template <typename T>
T* getComponent() {
auto it = components.find(typeid(T));
return (it != components.end()) ?
static_cast<T*>(it->second.get()) : nullptr;
}
void update() {
for(auto& [_, comp] : components) {
comp->update();
}
}
};
class Component {
public:
virtual void update() = 0;
virtual ~Component() = default;
};
// 具体组件实现
class Transform : public Component {
public:
void update() override { /* 更新位置信息 */ }
};
class PhysicsBody : public Component {
public:
void update() override { /* 物理模拟计算 */ }
};
// 使用示例
GameObject player;
player.addComponent<Transform>();
player.addComponent<PhysicsBody>();
player.update();
3.2 状态模式实现角色行为控制
class CharacterState {
public:
virtual void enter() = 0;
virtual void handleInput(char input) = 0;
virtual void update() = 0;
virtual ~CharacterState() = default;
};
class IdleState : public CharacterState {
public:
void enter() override { std::cout << "Entering Idle\n"; }
void handleInput(char input) override {
if(input == 'w') /* 切换到移动状态 */;
}
void update() override { /* 闲置动画更新 */ }
};
class StateMachine {
std::unique_ptr<CharacterState> currentState;
public:
void changeState(std::unique_ptr<CharacterState> newState) {
if(currentState) currentState->exit();
newState->enter();
currentState = std::move(newState);
}
void update() {
if(currentState) currentState->update();
}
};
// 使用示例
StateMachine fsm;
fsm.changeState(std::make_unique<IdleState>());
while(true) {
char input = getInput();
fsm.handleInput(input);
fsm.update();
}
五、设计模式最佳实践指南
1. 模式选择决策树
是否需要控制对象创建?
├─ 是 → 考虑工厂/建造者模式
├─ 否 → 是否需要扩展对象功能?
│ ├─ 是 → 装饰者/代理模式
│ └─ 否 → 是否需要算法切换?
│ ├─ 是 → 策略模式
│ └─ 否 → 是否需要状态管理?
│ ├─ 是 → 状态模式
│ └─ 否 → 观察者/命令模式
2. 典型代码异味与模式对应
代码问题 | 推荐模式 | 重构示例 |
---|---|---|
多重条件分支 | 策略/状态模式 | 用多态替代switch-case |
接口不兼容 | 适配器模式 | 包装旧接口为新接口 |
过度全局访问 | 单例→依赖注入 | 引入服务定位器 |
难以扩展功能 | 装饰者/组合模式 | 动态添加组件 |
紧耦合的对象通信 | 观察者/中介者模式 | 事件驱动架构 |
3. 现代C++设计原则
- 优先组合而非继承:使用std::variant/std::any实现运行时多态
- 利用RAII管理资源:智能指针自动管理模式对象生命周期
- 编译时多态优化:模板方法替代运行时虚函数分派
- 移动语义优化性能:在工厂模式中高效转移大型对象
- 类型擦除技术:使用std::function实现灵活的策略模式
六、常见陷阱与调试技巧
1. 单例模式的内存泄漏检测
使用Valgrind或AddressSanitizer检测未释放实例:
$ g++ -fsanitize=address -g singleton.cpp
$ ASAN_OPTIONS=detect_leaks=1 ./a.out
2. 观察者模式的循环引用排查
使用weak_ptr打破强引用循环:
class Subject {
std::vector<std::weak_ptr<Observer>> observers;
public:
void addObserver(std::weak_ptr<Observer> obs) {
observers.push_back(obs);
}
void notify() {
for(auto& weakObs : observers) {
if(auto obs = weakObs.lock()) {
obs->update();
}
}
}
};
3. 工厂模式的类型注册验证
静态断言确保类型安全:
template <typename T>
void registerType() {
static_assert(std::is_base_of_v<BaseProduct, T>,
"Must inherit from BaseProduct");
// 注册逻辑...
}
七、延伸阅读与工具推荐
1. 进阶学习资源
- 《Modern C++ Design》Andrei Alexandrescu
- 《C++ Core Guidelines》设计模式章节
- CppCon会议演讲:Modern C++ Design Patterns
2. 可视化设计工具
- PlantUML:模式UML图生成
- Doxygen:模式文档自动化
- Clang-Query:模式代码静态检测
3. 性能分析工具链
工具名称 | 用途 | 示例命令 |
---|---|---|
Perf | 函数级热点分析 | perf record ./app |
Hotspot | 可视化性能数据 | 图形化展示perf结果 |
Cachegrind | 缓存访问模式分析 | valgrind --tool=cachegrind ./app |