您的位置:首页 > 编程语言 > C语言/C++

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

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

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

[code]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的代码如下:

[code]#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>*
    {
        static Factory<T> 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子类。

[code]#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


[code]#ifndef WIDGET_H
#define WIDGET_H

#include "object.h"

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

#endif // WIDGET_H


[code]#include "widget.h"

Widget::Widget()
{

}

REGISTER_OBJECT_CLASS(Widget);


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

main.cpp

[code]#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中的几个宏封装了细节。但是比如

[code]#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: