注册模式(Registry Pattern)是一种用于动态管理对象创建和访问的设计模式。它通过一个中央注册表(Registry)存储可创建对象的元信息(如类名和构造函数),实现运行时动态创建对象和解耦对象使用与具体实现。


核心组成

  1. 基类(Base Class)
    所有可注册类的共同基类
  2. 注册表(Registry)
    全局单例,存储类名到构造函数的映射
  3. 注册宏(Registration Macro)
    自动将类注册到注册表
  4. 具体类(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;
}

模式优势

  1. 解耦
    调用方只需知道基类接口和类名字符串,无需包含具体类的头文件。
  2. 动态扩展
    添加新类时只需继承基类并注册,无需修改注册表代码。
  3. 集中管理
    所有可创建对象的信息在注册表中统一管理。
  4. 配置驱动
    可通过配置文件动态决定创建哪个类(如 config.json 中指定 "renderer": "OpenGLRenderer")。

应用场景

  • 插件系统(动态加载 DLL 中的类)
  • 工厂方法模式的扩展
  • 依赖注入容器
  • 根据配置文件创建对象(如游戏引擎的模块选择)

注意事项

  1. 线程安全
    注册表的单例实现(C++11 后静态局部变量线程安全)。
  2. 生命周期
    使用智能指针(如 std::unique_ptr)自动管理对象内存。
  3. 错误处理
    未找到类时抛出异常或返回空指针。
  4. 注册时机
    利用静态变量初始化在 main() 前自动注册。

推荐阅读

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐