创建型模式-自注册工厂方法
创建型模式-自注册工厂方法
目录
- 创建型模式-自注册工厂方法
- 1. 自注册工厂方法
- 1.1 介绍
- 1.2 实现
- 1.3 优缺点
- 优点
- 缺点
- 1. 自注册工厂方法

那一天我二十一岁,在我一生的黄金时代,我有好多奢望。我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样。可是我过二十一岁生日时没有预见到这一点。我觉得自己会永远生猛下去,什么也锤不了我。
《黄金时代》 王小波
文章大部分由AI生成
1. 自注册工厂方法
1.1 介绍
自注册工厂方法是一种创建型设计模式,它结合了工厂方法和自动注册机制。在这种模式中,派生类能够在程序启动时自动向工厂注册自己,无需手动维护创建映射表。这大大降低了扩展系统时的维护成本。
利用静态成员变量的初始化在
main函数执行前完成注册的特性,实现自动注册。
1.2 实现
第 1 步:定义基类和工厂
class IAnim
{
public:virtual ~IAnim() = default;virtual QString getName() = 0;virtual void say() = 0;void done(){qDebug() << getName() << ": " ;say();}
};class UFactory
{using funcCreator = std::function<std::unique_ptr<IAnim>()>;
public:static UFactory& inst(){static UFactory s_u_factory;return s_u_factory;}void registerClass(const QString& id, funcCreator creator){auto iter = _mapId2CreateFunc.find(id);if (iter != _mapId2CreateFunc.end()){qDebug() << "已经注册了: 跳过" << id;}else{_mapId2CreateFunc[id] = std::move(creator);}}std::unique_ptr<IAnim> create(const QString& id){auto iter = _mapId2CreateFunc.find(id);if (iter != _mapId2CreateFunc.end()){return iter.value()();}qCritical() << "未注册 Id: " << id;return nullptr;}
private:UFactory() = default;UFactory(const UFactory&) = delete;UFactory& operator = (const UFactory&) = delete;private:QMap<QString, funcCreator> _mapId2CreateFunc;
};
第 2 步:宏定义
#define REGISTER_CLASS(ClassName) \static bool ClassName##_registered = []() { \UFactory::inst().registerClass(#ClassName, \[]() -> std::unique_ptr<ClassName> { \return std::unique_ptr<ClassName>(new ClassName()); \}); \return true; \}();
第 3 步:定义子类
class UDog : public IAnim
{
public:virtual QString getName() override {return "Dog";}virtual void say() override {qDebug() << "Wang Wang...";}
};REGISTER_CLASS(UDog)class UCat : public IAnim
{
public:virtual QString getName() override {return "Cat";}virtual void say() override {qDebug() << "Miao Miao...";}
};
REGISTER_CLASS(UCat)
第 4步:使用
UFactory::inst().create("UDog")->done();
UFactory::inst().create("UCat")->done();已经注册了: 跳过 "UDog"
已经注册了: 跳过 "UCat"
"Dog" :
Wang Wang...
"Cat" :
Miao Miao...
1.3 优缺点
优点
| 优点 | 说明 |
|---|---|
| 扩展性好 | 新增类无需修改工厂代码,符合开闭原则 |
| 减少维护成本 | 无需手动维护注册映射表 |
| 配置驱动 | 可通过配置文件选择要创建的类 |
| 解耦 | 调用方只依赖基类和工厂,不依赖具体类 |
| 编译时检查 | 使用宏可以保证类型安全 |
缺点
| 缺点 | 说明 |
|---|---|
| 静态初始化顺序问题 | 跨编译单元的静态初始化顺序不确定,可能导致工厂在使用时未初始化 |
| 二进制膨胀 | 所有注册的类都会被链接进最终可执行文件 |
| 调试困难 | 静态初始化阶段的错误难以定位 |
| 依赖宏 | 需要宏辅助,可能影响代码可读性 |
| 类型名称冲突 | 使用类名字符串作为键,可能出现命名冲突 |
本文来自博客园,作者:Hakuon,转载请注明原文链接:https://www.cnblogs.com/Hakuon/p/19880105
