在C++框架的开发过程中,单一设计模式往往只能解决特定维度的开发问题,面对复杂的业务场景和框架扩展需求,将多个设计模式按照合理的逻辑进行组合,才能最大化发挥设计模式的优势,降低模块间的耦合度,提升代码的可维护性和扩展性。

常用设计模式组合场景
单例模式与工厂模式组合
单例模式可以保证某个类全局只有一个实例,工厂模式负责对象的创建逻辑封装,两者组合可以实现全局统一的对象创建管理,避免重复创建无状态的管理类实例。
下面是组合实现的示例代码:
#include <iostream>
#include <memory>
#include <unordered_map>
// 抽象产品类
class Product {
public:
virtual void use() = 0;
virtual ~Product() = default;
};
// 具体产品A
class ProductA : public Product {
public:
void use() override {
std::cout << "使用产品A" << std::endl;
}
};
// 具体产品B
class ProductB : public Product {
public:
void use() override {
std::cout << "使用产品B" << std::endl;
}
};
// 单例工厂类
class ProductFactory {
private:
// 私有构造函数,保证单例
ProductFactory() = default;
// 存储产品创建函数的映射
std::unordered_map<std::string, std::function<std::shared_ptr<Product>()>> creators;
public:
// 获取单例实例
static ProductFactory& getInstance() {
static ProductFactory instance;
return instance;
}
// 注册产品创建函数
void registerProduct(const std::string& type, std::function<std::shared_ptr<Product>()> creator) {
creators[type] = creator;
}
// 创建产品
std::shared_ptr<Product> createProduct(const std::string& type) {
auto it = creators.find(type);
if (it != creators.end()) {
return it->second();
}
return nullptr;
}
// 禁止拷贝和赋值
ProductFactory(const ProductFactory&) = delete;
ProductFactory& operator=(const ProductFactory&) = delete;
};
int main() {
// 注册产品
ProductFactory::getInstance().registerProduct("A", []() {
return std::make_shared<ProductA>();
});
ProductFactory::getInstance().registerProduct("B", []() {
return std::make_shared<ProductB>();
});
// 创建并使用产品
auto productA = ProductFactory::getInstance().createProduct("A");
if (productA) {
productA->use();
}
auto productB = ProductFactory::getInstance().createProduct("B");
if (productB) {
productB->use();
}
return 0;
}
观察者模式与策略模式组合
观察者模式用于实现对象间的消息通知,策略模式用于封装不同的算法逻辑,两者组合可以实现不同场景下动态切换通知处理逻辑,同时保证通知者和处理逻辑的解耦。
实现示例如下:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
// 通知策略接口
class NotifyStrategy {
public:
virtual void notify(const std::string& msg) = 0;
virtual ~NotifyStrategy() = default;
};
// 控制台通知策略
class ConsoleNotifyStrategy : public NotifyStrategy {
public:
void notify(const std::string& msg) override {
std::cout << "控制台通知: " << msg << std::endl;
}
};
// 文件通知策略
class FileNotifyStrategy : public NotifyStrategy {
public:
void notify(const std::string& msg) override {
std::cout << "文件通知: " << msg << std::endl;
}
};
// 观察者抽象类
class Observer {
public:
virtual void update(const std::string& msg) = 0;
virtual ~Observer() = default;
};
// 具体观察者,持有通知策略
class ConcreteObserver : public Observer {
private:
std::shared_ptr<NotifyStrategy> strategy;
public:
ConcreteObserver(std::shared_ptr<NotifyStrategy> s) : strategy(s) {}
void update(const std::string& msg) override {
if (strategy) {
strategy->notify(msg);
}
}
// 动态切换通知策略
void setStrategy(std::shared_ptr<NotifyStrategy> s) {
strategy = s;
}
};
// 被观察者类
class Subject {
private:
std::vector<std::shared_ptr<Observer>> observers;
public:
void attach(std::shared_ptr<Observer> observer) {
observers.push_back(observer);
}
void detach(std::shared_ptr<Observer> observer) {
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}
void notifyAll(const std::string& msg) {
for (auto& observer : observers) {
observer->update(msg);
}
}
};
int main() {
Subject subject;
auto consoleStrategy = std::make_shared<ConsoleNotifyStrategy>();
auto fileStrategy = std::make_shared<FileNotifyStrategy>();
auto observer1 = std::make_shared<ConcreteObserver>(consoleStrategy);
auto observer2 = std::make_shared<ConcreteObserver>(fileStrategy);
subject.attach(observer1);
subject.attach(observer2);
subject.notifyAll("框架初始化完成");
// 动态切换observer1的通知策略
observer1->setStrategy(fileStrategy);
subject.notifyAll("框架配置更新");
return 0;
}
设计模式组合的核心原则
- 职责单一原则:每个设计模式只负责解决自身对应的设计问题,组合时不要强行让某个模式承担额外的职责,避免逻辑混乱。
- 松耦合原则:组合后的模式之间尽量通过接口交互,避免直接依赖具体实现类,保证后续可以灵活替换某个模式的具体实现。
- 避免过度设计:不要为了组合而组合,只有当单一模式无法满足需求时再考虑组合,避免引入不必要的复杂度。
组合时的注意事项
在C++框架中组合设计模式时,需要注意内存管理问题,尤其是使用裸指针时容易出现内存泄漏或者悬垂指针,建议优先使用智能指针管理对象生命周期。另外,组合后的代码逻辑需要添加清晰的注释,说明每个模式的作用和组合的逻辑,方便后续维护。如果组合的模式较多,建议将不同模式的实现拆分到不同的模块中,避免单个类的职责过重。