C++中实现自动注册的工厂

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhx6044/article/details/50569482

很长时间没有更新博客了,不是博主懒,是因为博主在帮研究生妹子弄硕士论文,定位方面的,被imu,行人航迹,激光匹配各种虐,不说了,都是泪。

Factory模式,在工程中多用了创建派生类实例,内部一般使用switch-case根据不同的key去创建不同的派生类对象。

switch(Key) {
    case A: 
        return new A;
    case B:
        return new B;

    ...
}

对于继承体系简单的,这种还可以,如果对于一个复杂的体系,比如一个命令系统,最后其有100多个业务命令的类,那难道你还想把switch-case写成和懒婆娘的裹脚布一样,又臭又长,显然是不可以的,今天我们就来实现一个自动注册的工厂。
其实这个设计思路我在很早之前就看过,第一次好像是在cpp博客,第二次是在csdn,最近cpp社区“行知一”又看见了,但是他们那个只是一个demo代码,虽然这里我们只是简单的写写,但是尽量让其可以直接使用。
其实思路很简单,借助于map数据结构,标示类唯一的身份标记作为map的key,而value则是一个lambda表达式,其用来产生类实例。
factory的代码如下:

#ifndef FACTORY
#define FACTORY


#include <string>
#include <map>
#include <functional>

using namespace std;

template <typename T, typename K = std::string>
class Factory
{
public:


    typedef T type_value;

    template <typename N>
    struct register_h
    {
        register_h(const K& key)
        {
            Factory::instance()->m_creators[key] = []{ return new N; };
        }
    };


    static auto instance() -> Factory<T, K>*
    {
        static Factory<T, K> f;
        return &f;
    }

    auto creat(const K& key) -> T*
    {
        T* re = NULL;
        auto ite = m_creators.find(key);
        if (ite != m_creators.end()) {
            re = (ite->second)();
        }
        return re;
    }

    static auto produce(const K& key) -> T*
    {
        return Factory::instance()->creat(key);
    }

private:
    Factory() {}
    Factory(const Factory&) = delete;
    Factory(Factory&&) = delete;
    Factory& operator =(const Factory&) = delete;
    std::map<K, std::function<T*()>> m_creators;
};


#define CLASS_NAME(CLASS) #CLASS



#endif // FACTORY

默认使用string来作为键值。register_h类是很重要的一步,我们借组于其的实例化来完成注册动作。
其他的一些函数就是一些基础的功能,无非就是查找操作。
简单的使用demo,Object是我们的基类,然后其有一个Widget子类。

#ifndef OBJECT
#define OBJECT

#include "factory.h"


class Object
{
public:
    virtual ~Object() {}

};


#define FACTORY_OBJECT Factory<Object>


#define REGISTER_OBJECT_CLASS_KEY(CLASS, KEY) \
    FACTORY_OBJECT::register_h<CLASS> __##CLASS(KEY)


#define REGISTER_OBJECT_CLASS(CLASS) \
    REGISTER_OBJECT_CLASS_KEY(CLASS, CLASS_NAME(CLASS))



#endif // OBJECT
#ifndef WIDGET_H
#define WIDGET_H

#include "object.h"


class Widget : public Object
{
public:
    Widget();
};

#endif // WIDGET_H
#include "widget.h"

Widget::Widget()
{

}


REGISTER_OBJECT_CLASS(Widget);

REGISTER_OBJECT_CLASS(Widget);这句代码完成了注册,其实例化一个命名为__WidgtFactory<Object>::register_h<Widget>对象,在构造函数中现实了自动注册。

main.cpp

#include <iostream>
#include "widget.h"

using namespace std;







int main()
{
    Widget *p = static_cast<Widget*>(FACTORY_OBJECT::produce("Widget"));
    FACTORY_OBJECT::type_value* p1 = FACTORY_OBJECT::produce("Text");
    std::cout << p1;
    std::cout << "\n-----------------";
    std::cout << p;
    std::cout << "Hello World!" << std::endl;
    delete p;
    delete p1;
    return 0;
}

object.h中的几个宏封装了细节。但是比如

#ifndef MESSAGE
#define MESSAGE

#include "factory.h"

class Message
{

};



#define FACTORY_MESSAGE Factory<Message>


#define REGISTER_MESSAGE_CLASS_KEY(CLASS, KEY) \
    FACTORY_MESSAGE::register_h<CLASS> __##CLASS(KEY)


#define REGISTER_MESSAGE_CLASS(CLASS) \
    REGISTER_MESSAGE_CLASS_KEY(CLASS, CLASS_NAME(CLASS))


#endif // MESSAGE

新的一个类继承体系,宏写了一遍,但是这些宏的动作十分的相似,还是可以再抽象一下。

代码:https://github.com/ZhouBox/ccfactory.git

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页