设计模式是解决特定软件设计问题的经典方案,掌握它们能显著提升代码的可维护性和扩展性。本文详细解析C++中五种最常用的设计模式,附带完整代码示例和实战技巧。
一、设计模式概述
设计模式是面向对象编程中可复用的解决方案,它们源于工程师们多年积累的经验总结。在C++中应用设计模式能够:
-
提高代码复用性和扩展性
-
降低模块间的耦合度
-
提升系统的可维护性
-
使代码更符合开闭原则
下面我们将重点探讨五种最常用的设计模式及其C++实现。
二、工厂模式:对象创建的艺术
1. 简单工厂模式
// 抽象产品类
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品类
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing Circle" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "Drawing Rectangle" << endl;
}
};
// 简单工厂类
class ShapeFactory {
public:
static Shape* createShape(const string& type) {
if (type == "Circle") return new Circle();
if (type == "Rectangle") return new Rectangle();
return nullptr;
}
};
// 使用示例
int main() {
Shape* circle = ShapeFactory::createShape("Circle");
Shape* rect = ShapeFactory::createShape("Rectangle");
circle->draw(); // Drawing Circle
rect->draw(); // Drawing Rectangle
delete circle;
delete rect;
}
特点:
-
集中管理对象创建逻辑
-
客户端与具体类解耦
-
新增类型需修改工厂类(违反开闭原则)
2. 工厂方法模式
// 抽象工厂
class ShapeFactory {
public:
virtual Shape* createShape() = 0;
virtual ~ShapeFactory() = default;
};
// 具体工厂
class CircleFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Circle();
}
};
class RectangleFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Rectangle();
}
};
// 使用示例
int main() {
ShapeFactory* circleFactory = new CircleFactory();
Shape* circle = circleFactory->createShape();
circle->draw(); // Drawing Circle
delete circle;
delete circleFactory;
}
优势:
-
完全遵循开闭原则
-
每个产品对应独立工厂
-
支持多态性创建
三、单例模式:确保唯一实例
线程安全实现(C++11)
class Singleton {
private:
Singleton() = default; // 私有构造函数
~Singleton() = default; // 私有析构函数
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton& getInstance() {
static Singleton instance; // C++11保证线程安全
return instance;
}
void showMessage() {
cout << "Singleton instance working!" << endl;
}
};
// 使用示例
int main() {
Singleton::getInstance().showMessage();
}
应用场景:
-
配置文件读取器
-
日志记录器
-
数据库连接池
-
线程池管理
四、观察者模式:状态变化的广播机制
#include <vector>
#include <algorithm>
// 观察者接口
class Observer {
public:
virtual void update(float temp) = 0;
virtual ~Observer() = default;
};
// 主题接口
class Subject {
private:
vector<Observer*> observers;
float temperature;
public:
void attach(Observer* obs) {
observers.push_back(obs);
}
void detach(Observer* obs) {
observers.erase(remove(observers.begin(), observers.end(), obs), observers.end());
}
void notify() {
for (auto obs : observers) {
obs->update(temperature);
}
}
void setTemperature(float temp) {
temperature = temp;
notify();
}
};
// 具体观察者
class Display : public Observer {
public:
void update(float temp) override {
cout << "Temperature updated: " << temp << "°C" << endl;
}
};
// 使用示例
int main() {
Subject weatherStation;
Display display1, display2;
weatherStation.attach(&display1);
weatherStation.attach(&display2);
weatherStation.setTemperature(25.5); // 所有显示器自动更新
}
模式结构:
Subject(主题) │ ├── attach(Observer) ├── detach(Observer) └── notify() │ ▼ Observer(观察者接口) ▲ │ │ ConcreteObserver(具体观察者)
五、策略模式:算法的自由切换
// 策略接口
class SortingStrategy {
public:
virtual void sort(vector<int>& data) = 0;
virtual ~SortingStrategy() = default;
};
// 具体策略
class BubbleSort : public SortingStrategy {
public:
void sort(vector<int>& data) override {
cout << "Using Bubble Sort" << endl;
// 实现冒泡排序...
}
};
class QuickSort : public SortingStrategy {
public:
void sort(vector<int>& data) override {
cout << "Using Quick Sort" << endl;
// 实现快速排序...
}
};
// 上下文类
class Sorter {
private:
SortingStrategy* strategy;
public:
Sorter(SortingStrategy* strat = nullptr) : strategy(strat) {}
void setStrategy(SortingStrategy* strat) {
strategy = strat;
}
void executeSort(vector<int>& data) {
if (strategy) strategy->sort(data);
}
};
// 使用示例
int main() {
vector<int> data = {5, 2, 7, 1, 9};
Sorter sorter;
sorter.setStrategy(new BubbleSort());
sorter.executeSort(data);
sorter.setStrategy(new QuickSort());
sorter.executeSort(data);
}
优势对比:
模式 | 优点 | 缺点 |
---|---|---|
工厂模式 | 解耦创建逻辑,代码复用 | 增加类数量 |
单例模式 | 全局唯一访问点,节省资源 | 测试困难,可能产生隐藏依赖 |
观察者模式 | 松耦合,动态订阅 | 通知顺序不可控 |
策略模式 | 算法自由切换,避免条件语句 | 客户端需了解策略差异 |
六、适配器模式:不兼容接口的桥梁
// 已有接口(不兼容)
class LegacyRectangle {
public:
void draw(int x1, int y1, int x2, int y2) {
cout << "LegacyRectangle: (" << x1 << "," << y1
<< ") to (" << x2 << "," << y2 << ")" << endl;
}
};
// 目标接口
class Rectangle {
public:
virtual void draw(int x, int y, int w, int h) = 0;
virtual ~Rectangle() = default;
};
// 适配器
class RectangleAdapter : public Rectangle {
private:
LegacyRectangle legacyRect;
public:
void draw(int x, int y, int w, int h) override {
// 转换参数调用旧接口
legacyRect.draw(x, y, x + w, y + h);
}
};
// 使用示例
int main() {
Rectangle* rect = new RectangleAdapter();
rect->draw(10, 20, 30, 40); // 输出: LegacyRectangle: (10,20) to (40,60)
}
适用场景:
-
集成遗留代码
-
使用第三方库接口
-
统一多个类的接口
七、如何选择设计模式
-
创建型问题(对象创建)
-
工厂模式:需要统一管理创建逻辑
-
单例模式:要求全局唯一实例
-
-
结构型问题(对象组合)
-
适配器模式:接口转换需求
-
装饰器模式:动态添加功能
-
-
行为型问题(对象交互)
-
观察者模式:一对多状态通知
-
策略模式:算法灵活切换
-
黄金法则:不要为了用模式而用模式,当简单实现无法优雅解决问题时再考虑设计模式。
八、总结
设计模式是C++高级开发的必备技能,关键要点:
-
工厂模式解决对象创建问题
-
单例模式确保全局唯一访问
-
观察者模式实现松耦合通知
-
策略模式支持运行时算法切换
-
适配器模式解决接口兼容问题
最佳实践建议:
-
优先使用对象组合而非类继承
-
针对接口编程而非具体实现
-
遵循单一职责原则
-
小步重构引入模式,避免过度设计
掌握这些设计模式将显著提升你的C++架构设计能力。每种模式都有其适用场景,在实际项目中灵活组合使用,才能发挥最大价值。