我能不能设计一种“灵活可变的单例”,可以在运行时决定用哪个派生类作为当前单例?并且由一个管理类来负责这些单例的创建和切换?
答案是:✅ 可以!
这其实是一个经典的设计问题,解决方案叫做:
🧠「单例管理器 + 多态派生类」的组合
✅ 核心思路:
- 定义一个抽象基类(接口)
- 定义多个派生类
- 定义一个全局的单例管理器,持有当前单例指针
- 外部可以通过配置/调用注册一个派生类为当前的单例实现
✅ 示例代码(可灵活切换派生类单例)
1. 抽象接口类:
class Service {
public:
virtual void doWork() = 0;
virtual ~Service() = default;
};
2. 两个派生类:
class RealService : public Service {
public:
void doWork() override {
cout << "RealService doing work\n";
}
};
class MockService : public Service {
public:
void doWork() override {
cout << "MockService doing work\n";
}
};
3. 单例管理器类(控制用哪个派生类):
class ServiceManager {
private:
static Service* instance;
public:
// 设置当前的单例实现(可传不同派生类)
static void setInstance(Service* svc) {
if (instance) delete instance;
instance = svc;
}
// 获取当前单例
static Service& getInstance() {
if (!instance) {
throw std::runtime_error("Service not initialized");
}
return *instance;
}
// 释放资源(可选)
static void destroy() {
delete instance;
instance = nullptr;
}
};
// 初始化 static 成员
Service* ServiceManager::instance = nullptr;
4. 使用方式:
int main() {
// 设置当前实现为 RealService(或根据配置选择)
ServiceManager::setInstance(new RealService());
ServiceManager::getInstance().doWork(); // RealService doing work
// 切换为 MockService
ServiceManager::setInstance(new MockService());
ServiceManager::getInstance().doWork(); // MockService doing work
ServiceManager::destroy(); // 释放资源
}
✅ 这个设计的优点:
| 特性 | 说明 |
|---|---|
| 灵活性强 | 可以在运行时根据条件/配置切换不同实现 |
| 避免耦合 | 不直接依赖具体派生类,只通过抽象接口调用 |
| 线程安全(可扩展) | 可加入互斥锁保护 get/setInstance 实现线程安全 |
| 遵循开闭原则 | 增加新派生类无需修改核心逻辑 |
✅ 实际应用场景:
- Web 服务中:根据运行模式切换真实服务和 Mock 服务
- 多平台组件:同一接口,不同平台不同实现
- 热更新:通过注册新子类替换旧服务(前提是接口一致)
✅ 进阶:自动注册 + 工厂形式
如果你希望自动注册派生类并按字符串选择,可以扩展成:
ServiceManager::setInstance(Factory::create("RealService"));
我可以帮你做一版带类名注册映射表 + 工厂 + 自动构造函数注册的版本,适合中大型框架使用。你需要吗?
543

被折叠的 条评论
为什么被折叠?



