很长时间没有更新博客了,不是博主懒,是因为博主在帮研究生妹子弄硕士论文,定位方面的,被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>*
{
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子类。
#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);
这句代码完成了注册,其实例化一个命名为__Widgt的Factory<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