A factory that implements automatic registration in C ++
I haven't updated my blog for a long time. It's not because the blogger is not lazy. It's because the blogger is helping graduate students get master's thesis, positioning, imu, pedestrian track, laser match, and abuse, all are tears.
Factory mode. You can create a derived class instance in the project. Generally, switch-case is used internally to create different derived class objects based on different keys.
switch(Key) { case A: return new A; case B: return new B; ...}
For a simple inheritance system, this is also acceptable. For a complex system, such as a command system, there are at last more than 100 business commands, then, do you want to write the switch-case statement as long as the cloth of the lazy mother-in-law? Obviously, this is not acceptable. Today we will implement an automatic registration factory.
In fact, I have read this design idea a long time ago. For the first time, it seems to be a cpp blog, and for the second time it was in csdn. Recently, the cpp community "Zhiyi" saw it again, however, they are just a demo code. Although we only write it in simple mode, we try to make it usable directly.
In fact, the idea is very simple. With the help of the map data structure, the unique ID mark of the class is used as the map key, while the value is a lambda expression, which is used to generate class instances.
The factory Code is as follows:
#ifndef FACTORY#define FACTORY#include
#include
#include
using namespace std;template
class Factory{public: typedef T type_value; template
struct register_h { register_h(const K& key) { Factory::instance()->m_creators[key] = []{ return new N; }; } }; static auto instance() -> Factory
* { static Factory
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
> m_creators;};#define CLASS_NAME(CLASS) #CLASS#endif // FACTORY
String is used as the key value by default.register_h
Class is an important step. We use the group's Instantiation to complete the registration action.
Some other functions are basic functions, which are nothing more than search operations.
Simple use of demo, Object is our base class, and then it has a Widget subclass.
#ifndef OBJECT#define OBJECT#include "factory.h"class Object{public: virtual ~Object() {}};#define FACTORY_OBJECT Factory#define REGISTER_OBJECT_CLASS_KEY(CLASS, KEY) \ FACTORY_OBJECT::register_h
__##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);
The Code has been registered, and its instantiation is named_ WidgtOfFactory::register_h
Object, which is automatically registered in the constructor.
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;}
Several Macros in object. h encapsulate the details. However, for example
#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
A new class inheritance system is written by macros. However, these macro actions are very similar and can be abstracted.