在软件开发领域,设计模式是解决反复出现问题的通用解决方案。掌握设计模式不仅能提升代码质量,还能更高效地与其他开发者协作。
一、单例模式:确保全局唯一实例
定义:单例模式确保一个类只有一个实例,并提供一个全局访问点。
应用场景:
- 日志记录器
- 配置管理器
- 数据库连接池
Meyers’ Singleton实现(C++11+)
class Logger {
public:
// 获取单例实例的静态方法
static Logger& getInstance() {
static Logger instance; // C++11保证线程安全
return instance;
}
// 禁用拷贝构造和赋值运算符
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
// 业务方法
void log(const std::string& message) {
std::cout << "[LOG] " << message << std::endl;
}
private:
Logger() = default; // 私有构造函数
~Logger() = default;
};
// 使用示例
void example() {
Logger::getInstance().log("System started");
}
技术要点:
- 静态局部变量在首次调用时初始化(C++11起线程安全)
- 删除拷贝构造和赋值运算符防止克隆
- 私有构造函数确保无法外部实例化
二、工厂模式:解耦对象创建逻辑
定义:工厂模式将对象创建逻辑封装在一个工厂类/方法中,实现创建和使用的分离。
应用场景:
- 对象创建过程复杂
- 根据条件动态创建对象
- 框架扩展点设计
简单工厂实现
// 抽象产品类
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品类
class Circle : public Shape {
public:
void draw() override { std::cout << "Drawing Circle" << std::endl; }
};
class Square : public Shape {
public:
void draw() override { std::cout << "Drawing Square" << std::endl; }
};
// 工厂类
class ShapeFactory {
public:
static std::unique_ptr<Shape> createShape(const std::string& type) {
if (type == "circle") return std::make_unique<Circle>();
if (type == "square") return std::make_unique<Square>();
throw std::invalid_argument("Invalid shape type");
}
};
// 使用示例
void factoryExample() {
auto circle = ShapeFactory::createShape("circle");
circle->draw();
}
进阶技巧:
- 使用枚举替代字符串参数
- 结合模板实现参数化工厂
- 注册式工厂支持动态扩展
三、观察者模式:构建事件驱动系统
定义:观察者模式定义了一种一对多的依赖关系,当一个对象状态变化时,所有依赖者都会收到通知。
应用场景:
- 消息通知系统
- GUI事件处理
- 状态监控系统
标准实现方案
#include <vector>
#include <memory>
#include <string>
// 观察者接口
class Observer {
public:
virtual void update(const std::string& message) = 0;
virtual ~Observer() = default;
};
// 主题接口
class Subject {
public:
virtual void attach(std::shared_ptr<Observer> observer) = 0;
virtual void detach(std::shared_ptr<Observer> observer) = 0;
virtual void notify(const std::string& message) = 0;
virtual ~Subject() = default;
};
// 具体主题
class NewsPublisher : public Subject {
private:
std::vector<std::shared_ptr<Observer>> observers;
std::string latestNews;
public:
void attach(std::shared_ptr<Observer> observer) override {
observers.push_back(observer);
}
void detach(std::shared_ptr<Observer> observer) override {
observers.erase(
std::remove(observers.begin(), observers.end(), observer),
observers.end()
);
}
void notify(const std::string& message) override {
for (auto& observer : observers) {
observer->update(message);
}
}
void publishNews(const std::string& news) {
latestNews = news;
notify(latestNews);
}
};
// 具体观察者
class NewsSubscriber : public Observer {
private:
std::string name;
public:
explicit NewsSubscriber(const std::string& name) : name(name) {}
void update(const std::string& message) override {
std::cout << name << " received: " << message << std::endl;
}
};
// 使用示例
void observerExample() {
auto publisher = std::make_shared<NewsPublisher>();
auto subscriber1 = std::make_shared<NewsSubscriber>("Alice");
auto subscriber2 = std::make_shared<NewsSubscriber>("Bob");
publisher->attach(subscriber1);
publisher->attach(subscriber2);
publisher->publishNews("Breaking: Design Patterns Explained!");
}
高级应用:
- 使用智能指针管理观察者生命周期
- 实现多级观察者层次结构
- 异步通知机制提升性能
四、策略模式:封装可互换算法
定义:策略模式将算法封装成独立的策略类,使它们可以互相替换,让算法变化独立于客户端。
应用场景:
- 排序算法切换
- 支付方式选择
- 压缩算法切换
策略模式实现
#include <vector>
#include <memory>
#include <iostream>
// 策略接口
class SortStrategy {
public:
virtual void sort(std::vector<int>& data) = 0;
virtual ~SortStrategy() = default;
};
// 具体策略
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
std::cout << "Sorting using QuickSort" << std::endl;
// 实现快速排序逻辑
}
};
class MergeSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
std::cout << "Sorting using MergeSort" << std::endl;
// 实现归并排序逻辑
}
};
// 上下文类
class Sorter {
private:
std::unique_ptr<SortStrategy> strategy;
public:
explicit Sorter(std::unique_ptr<SortStrategy> strategy)
: strategy(std::move(strategy)) {}
void setStrategy(std::unique_ptr<SortStrategy> newStrategy) {
strategy = std::move(newStrategy);
}
void executeSort(std::vector<int>& data) {
strategy->sort(data);
}
};
// 使用示例
void strategyExample() {
std::vector<int> data = {5, 3, 8, 1, 4};
// 使用快速排序
Sorter sorter(std::make_unique<QuickSort>());
sorter.executeSort(data);
// 动态切换为归并排序
sorter.setStrategy(std::make_unique<MergeSort>());
sorter.executeSort(data);
}
设计优势:
- 符合开闭原则(对扩展开放,对修改关闭)
- 消除大量条件判断语句
- 便于单元测试不同策略
五、总结与最佳实践
单例模式:
- 使用Meyers实现保证线程安全
- 避免在性能敏感场景使用锁机制
工厂模式:
- 小型项目可使用简单工厂
- 大型框架建议使用抽象工厂
观察者模式:
- 注意避免循环引用导致内存泄漏
- 考虑使用弱引用管理观察者
策略模式:
- 结合工厂模式动态创建策略
- 考虑使用函数对象替代策略类
设计模式是经验的总结而非教条,在实际开发中应根据需求灵活运用,避免过度设计。