设计模式在现代C++中的应用
设计模式是解决常见软件设计问题的可重用模板。在现代C++(C++11 及更高版本)中,新特性如智能指针、lambda 表达式、移动语义和 std::function 等,使设计模式的实现更简洁、安全和高效。下面我将逐步介绍几种常见设计模式在现代C++中的应用,包括代码示例。每个模式会先简要描述,然后解释现代C++特性如何优化实现,并提供实际代码。
1. 单例模式(Singleton)
单例模式确保一个类只有一个实例,并提供全局访问点。在现代C++中,使用智能指针(如 std::unique_ptr)可以避免内存泄漏,并确保线程安全(通过 C++11 的 std::call_once)。
现代C++实现关键点:
- 使用
std::unique_ptr管理实例。 - 用
std::call_once保证线程安全的初始化。 - 禁用拷贝和移动构造函数。
cpp
#include <memory>
#include <mutex>
class Singleton {
private:
static std::unique_ptr<Singleton> instance;
static std::once_flag flag;
Singleton() {} // 私有构造函数
Singleton(const Singleton&) = delete; // 禁用拷贝
Singleton& operator=(const Singleton&) = delete; // 禁用赋值
public:
static Singleton& getInstance() {
std::call_once(flag, []() {
instance = std::make_unique<Singleton>();
});
return *instance;
}
void doSomething() {
// 示例方法
}
};
std::unique_ptr<Singleton> Singleton::instance = nullptr;
std::once_flag Singleton::flag;
应用场景:全局配置管理或日志系统,确保只有一个实例共享资源。
2. 工厂模式(Factory)
工厂模式通过一个接口创建对象,而不指定具体类。现代C++中,lambda 表达式和 std::function 可以简化工厂的实现,避免复杂的继承层次。
现代C++实现关键点:
- 使用
std::function存储创建函数。 - 利用 lambda 表达式定义对象创建逻辑。
- 结合
std::unordered_map实现灵活的对象注册。
cpp
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
class Product {
public:
virtual ~Product() = default;
virtual void use() = 0;
};
class ConcreteProductA : public Product {
public:
void use() override {
// 实现A
}
};
class ConcreteProductB : public Product {
public:
void use() override {
// 实现B
}
};
class Factory {
private:
std::unordered_map<std::string, std::function<std::unique_ptr<Product>()>> creators;
public:
void registerCreator(const std::string& type, std::function<std::unique_ptr<Product>()> creator) {
creators[type] = creator;
}
std::unique_ptr<Product> create(const std::string& type) {
if (auto it = creators.find(type); it != creators.end()) {
return it->second(); // 调用lambda创建对象
}
return nullptr;
}
};
// 使用示例
int main() {
Factory factory;
factory.registerCreator("A", []() -> std::unique_ptr<Product> { return std::make_unique<ConcreteProductA>(); });
factory.registerCreator("B", []() -> std::unique_ptr<Product> { return std::make_unique<ConcreteProductB>(); });
auto product = factory.create("A");
if (product) {
product->use();
}
}
应用场景:插件系统或依赖注入,动态创建不同类型的对象。
3. 观察者模式(Observer)
观察者模式定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者自动更新。现代C++中,std::function 和 lambda 表达式替代了传统的接口继承,使代码更灵活。
现代C++实现关键点:
- 使用
std::function存储观察者回调。 - 结合
std::vector管理多个观察者。 - 利用 lambda 简化事件处理。
cpp
#include <functional>
#include <vector>
#include <iostream>
class Subject {
private:
std::vector<std::function<void(int)>> observers;
public:
void attach(std::function<void(int)> observer) {
observers.push_back(observer);
}
void notify(int data) {
for (auto& observer : observers) {
observer(data); // 调用回调函数
}
}
};
// 使用示例
int main() {
Subject subject;
// 添加观察者1:使用lambda
subject.attach([](int data) {
std::cout << "Observer 1: " << data << std::endl;
});
// 添加观察者2:使用lambda
subject.attach([](int data) {
std::cout << "Observer 2: " << data << std::endl;
});
subject.notify(42); // 触发更新
}
应用场景:GUI 事件处理或实时数据监控,解耦发布者和订阅者。
4. 策略模式(Strategy)
策略模式定义一系列算法,并使它们可互换。现代C++中,std::function 或模板参数可以替代虚函数,减少运行时开销并提升灵活性。
现代C++实现关键点:
- 使用
std::function封装策略函数。 - 或使用模板在编译时绑定策略。
- 避免虚函数开销。
cpp
#include <functional>
#include <iostream>
class Context {
private:
std::function<int(int, int)> strategy; // 策略函数
public:
void setStrategy(std::function<int(int, int)> strat) {
strategy = strat;
}
int executeStrategy(int a, int b) {
return strategy(a, b);
}
};
// 使用示例
int main() {
Context context;
// 策略1:加法
context.setStrategy([](int a, int b) -> int { return a + b; });
std::cout << "10 + 5 = " << context.executeStrategy(10, 5) << std::endl;
// 策略2:乘法
context.setStrategy([](int a, int b) -> int { return a * b; });
std::cout << "10 * 5 = " << context.executeStrategy(10, 5) << std::endl;
}
应用场景:排序算法或支付方式选择,动态切换行为。
总结
在现代C++中,设计模式的应用变得更简洁和安全:
- 优势 :智能指针管理内存,避免泄漏;lambda 和
std::function替代继承,减少样板代码;移动语义提升性能。 - 建议 :优先使用现代特性(如 C++17 的
std::optional或 C++20 的 concepts)来简化模式实现。实际开发中,结合具体需求选择模式,避免过度设计。 - 注意事项 :确保线程安全(使用
std::mutex或原子操作),并遵循 RAII 原则(Resource Acquisition Is Initialization)管理资源。
通过以上示例,您可以看到现代C++如何使设计模式更易于实现和维护。如果需要深入某个模式或更多模式(如装饰器或适配器),请提供进一步细节!