【设计模式】其它经典模式-注册模式(Registry Pattern)
·
注册模式(Registry Pattern)是一种用于动态管理对象创建和访问的设计模式。它通过一个中央注册表(Registry)存储可创建对象的元信息(如类名和构造函数),实现运行时动态创建对象和解耦对象使用与具体实现。
核心组成
- 基类(Base Class)
所有可注册类的共同基类 - 注册表(Registry)
全局单例,存储类名到构造函数的映射 - 注册宏(Registration Macro)
自动将类注册到注册表 - 具体类(Derived Classes)
继承基类并注册自己
代码实现
步骤 1:定义基类
// Base.h
#include <memory>
class Base {
public:
virtual ~Base() = default;
virtual void execute() = 0; // 纯虚函数接口
};
using BasePtr = std::unique_ptr<Base>; // 智能指针别名
步骤 2:实现注册表(关键部分)
// Registry.h
#include <map>
#include <functional>
#include <string>
#include <memory>
#include <stdexcept>
class Registry {
public:
// 获取单例实例
static Registry& instance() {
static Registry instance;
return instance;
}
// 注册类:将类名与构造函数关联
void registerClass(const std::string& name, std::function<Base*()> creator) {
registryMap[name] = creator;
}
// 根据类名创建对象
BasePtr create(const std::string& name) {
auto it = registryMap.find(name);
if (it == registryMap.end()) {
throw std::runtime_error("Class not registered: " + name);
}
return BasePtr(it->second()); // 调用构造函数
}
private:
std::map<std::string, std::function<Base*()>> registryMap;
// 单例模式:禁止外部构造/拷贝
Registry() = default;
Registry(const Registry&) = delete;
void operator=(const Registry&) = delete;
};
步骤 3:创建注册辅助类和宏
// Registration.h
#include "Registry.h"
// 注册模板类:在构造时自动注册
template <typename T>
class AutoRegister {
public:
explicit AutoRegister(const std::string& name) {
Registry::instance().registerClass(name, []() -> Base* {
return new T(); // 返回新对象
});
}
};
// 注册宏(简化使用)
#define REGISTER_CLASS(CLASS_NAME) \
static AutoRegister<CLASS_NAME> autoRegister##CLASS_NAME(#CLASS_NAME)
步骤 4:定义具体类并注册
// DerivedClasses.h
#include "Base.h"
#include "Registration.h"
// 具体类 A
class ClassA : public Base {
public:
void execute() override {
std::cout << "ClassA operation executed\n";
}
};
REGISTER_CLASS(ClassA); // 注册 ClassA
// 具体类 B
class ClassB : public Base {
public:
void execute() override {
std::cout << "ClassB operation executed\n";
}
};
REGISTER_CLASS(ClassB); // 注册 ClassB
步骤 5:使用注册表动态创建对象
// main.cpp
#include "Registry.h"
int main() {
// 动态创建对象(无需知道具体类型)
BasePtr objA = Registry::instance().create("ClassA");
BasePtr objB = Registry::instance().create("ClassB");
objA->execute(); // 输出: ClassA operation executed
objB->execute(); // 输出: ClassB operation executed
// 错误示例:尝试创建未注册的类
try {
BasePtr objC = Registry::instance().create("ClassC");
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << "\n"; // 输出: Class not registered: ClassC
}
return 0;
}
模式优势
- 解耦
调用方只需知道基类接口和类名字符串,无需包含具体类的头文件。 - 动态扩展
添加新类时只需继承基类并注册,无需修改注册表代码。 - 集中管理
所有可创建对象的信息在注册表中统一管理。 - 配置驱动
可通过配置文件动态决定创建哪个类(如config.json中指定"renderer": "OpenGLRenderer")。
应用场景
- 插件系统(动态加载 DLL 中的类)
- 工厂方法模式的扩展
- 依赖注入容器
- 根据配置文件创建对象(如游戏引擎的模块选择)
注意事项
- 线程安全
注册表的单例实现(C++11 后静态局部变量线程安全)。 - 生命周期
使用智能指针(如std::unique_ptr)自动管理对象内存。 - 错误处理
未找到类时抛出异常或返回空指针。 - 注册时机
利用静态变量初始化在main()前自动注册。
推荐阅读
更多推荐
所有评论(0)