在C++中,工厂模式配合模板自动注册可以显著降低新增类型的接入成本。核心思路是通过模板基类提供统一创建接口,利用宏在编译期生成注册代码,并借助Map的静态初始化将类型信息写入全局工厂表。

设计思路
我们定义一个抽象产品基类,以及一个模板工厂类。每个具体产品继承基类,并通过宏在全局作用域注册自己到工厂的Map中。由于静态变量的初始化发生在main之前,程序启动时注册即完成。
核心组件
- 产品基类:定义纯虚接口
- 工厂类:维护string到创建函数的Map
- 注册宏:生成静态注册对象与创建函数
代码实现
工厂与基类定义
#include <iostream>
#include <string>
#include <map>
#include <functional>
// 产品抽象基类
class Product {
public:
virtual void use() = 0;
virtual ~Product() {}
};
// 工厂类,使用模板实现自动注册
class Factory {
public:
using Creator = std::function<Product*()>;
static std::map<std::string, Creator>& registry() {
static std::map<std::string, Creator> reg;
return reg;
}
static Product* create(const std::string& name) {
auto& reg = registry();
if (reg.find(name) == reg.end()) return nullptr;
return reg[name]();
}
};
// 自动注册模板类
template <typename T>
class AutoRegister {
public:
AutoRegister(const std::string& name) {
Factory::registry()[name] = []() -> Product* {
return new T();
};
}
};
注册宏定义
通过宏隐藏注册细节,让具体产品只需声明一次即可完成注册。
// 定义注册宏,生成静态注册对象
#define REGISTER_PRODUCT(ClassName, Key)
class ClassName##_Registrar {
public:
static AutoRegister<ClassName> reg;
};
AutoRegister<ClassName> ClassName##_Registrar::reg(Key);
具体产品与使用
// 具体产品A
class ProductA : public Product {
public:
void use() override { std::cout << "Using ProductA" << std::endl; }
};
REGISTER_PRODUCT(ProductA, "A")
// 具体产品B
class ProductB : public Product {
public:
void use() override { std::cout << "Using ProductB" << std::endl; }
};
REGISTER_PRODUCT(ProductB, "B")
int main() {
Product* pa = Factory::create("A");
if (pa) pa->use();
Product* pb = Factory::create("B");
if (pb) pb->use();
delete pa;
delete pb;
return 0;
}
注意事项
静态初始化顺序在不同编译单元间未定义,但上述代码中Map通过函数内static局部变量返回,避免了跨文件初始化竞态。新增产品时只需写好类并调用REGISTER_PRODUCT宏,无需修改工厂主体。
该模式适合类型较多且频繁扩展的系统,但不宜用于注册耗时操作,以免拖慢启动。
小结
借助C++模板、宏与Map静态初始化,我们能以极低侵入性实现工厂的自动注册,提升代码整洁度与维护效率。