很長時間沒有更新博客了,不是博主懶,是因為博主在幫研究生妹子弄碩士論文,定位方面的,被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
#include
默認使用string來作為鍵值。register_h
類是很重要的一步,我們借組於其的實例化來完成注冊動作。
其他的一些函數就是一些基礎的功能,無非就是查找操作。
簡單的使用demo,Object是我們的基類,然後其有一個Widget子類。
#ifndef OBJECT
#define OBJECT
#include "factory.h"
class Object
{
public:
virtual ~Object() {}
};
#define FACTORY_OBJECT Factory
#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
對象,在構造函數中現實了自動注冊。
main.cpp
#include
#include "widget.h"
using namespace std;
int main()
{
Widget *p = static_cast(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
#define REGISTER_MESSAGE_CLASS_KEY(CLASS, KEY) \
FACTORY_MESSAGE::register_h __##CLASS(KEY)
#define REGISTER_MESSAGE_CLASS(CLASS) \
REGISTER_MESSAGE_CLASS_KEY(CLASS, CLASS_NAME(CLASS))
#endif // MESSAGE
新的一個類繼承體系,宏寫了一遍,但是這些宏的動作十分的相似,還是可以再抽象一下。