在前一篇笔记中我们介绍了工厂方法模式,示例的类图如下:

考虑一种情况:现在要在程序运行时,根据外部资源,动态的实例化对象。也就是说在编译期我们无法知道要实例化的对象的类型。因此在实例化的过程中,就需要加以判断。
例如,在我的例子中,要根据连接到主机的相机来实例化相机对象,那么客户端(使用工厂方法创建实例的一方)使用工厂方法模式创建对象的时候,代码可能是这样:
- //运行时确定数组大小,且确定后不可改变
- auto camera_devices_ = std::make_unique<std::shared_ptr<CameraDevice>[]>(onlined_camera_num_);
-
- for(int i = 0; i < onlined_camera_num_; ++i)
- {
- std::shared_ptr<CameraDeviceFactory> factory;
- if("Sick" == camera_name[i]) //camera_name[i]中元素是提前获取的与连接的相机对应的供应商名称
- factory = std::make_shared<SickCameraFactory>();
- else if("Basler" == camera_name[i])
- factory = std::make_shared<BaslerCameraFactory>();
- else if("Huaray" == camera_name[i])
- factory = std::make_shared<HuarayCameraFactory>();
- camera_devices_[i] = factory->CreateCamera();
- }
虽然工厂方法模式遵循了开闭原则,即当有新类型的时候,无需修改现有的代码,只需新加产品类和对应工厂类即可。但是对于客户端来说,当需要实例化的类型数量增加时,就需要新增else if去适配,这使得客户端代码变得冗长且难以维护。
为了解决上面问题,我们可以实现一个类型的注册表,允许动态创建对象。这种方法通过将关键字映射到构造函数指针,使得可以根据字符串名称动态地实例化对象。
- #ifndef Reflection_H
- #define Reflection_H
-
- #include <map>
- #include <string>
-
- template <typename T, typename... ArgType>
- void* CreateInstance(ArgType... args)
- {
- return new T(args...);
- }
-
- //需要反射的类使用该宏注册
- #ifndef ReflectRegister
- #define ReflectRegister(identifier, class_name, ...) \
- static bool __type##class_name = Object::Register(identifier, (void*)CreateInstance<class_name, ##__VA_ARGS__>);
- #endif
-
- class Object
- {
- public:
- template <typename BaseClass, typename... ArgType>
- static BaseClass *CreateObject(const std::string &vendor_name, ArgType... args)
- {
- using CreateFactory = BaseClass *(*)(ArgType...);
- auto& class_map = GetStaticFuncMap();
- auto iter = class_map.find(vendor_name);
- if (iter == class_map.end())
- {
- CRRC_ERROR("class_name not found in map");
- return nullptr;
- }
- else
- {
- CRRC_DEBUG("class_name found in map");
- return reinterpret_cast<CreateFactory>(class_map[vendor_name])(args...);
- }
-
- }
-
- //向map中注册关键字和类的构造函数
- static bool Register(const std::string &vendor_name, void *ctor_ptr)
- {
- CRRC_DEBUG("Register class_name:"<<vendor_name);
- GetStaticFuncMap()[vendor_name] = ctor_ptr;
- return true;
- }
-
- private:
- //获取全局唯一的map
- //map记录了关键字和类的构造函数的映射关系
- static std::map<std::string, void*>& GetStaticFuncMap()
- {
- static std::map<std::string, void*> class_map_;
- return class_map_;
- }
-
- };
-
- #endif //Reflection_H
在具体相机工厂中,我们可以使用ReflectRegister注册此类(以Basler相机为例,其余类似):
- class BaslerCameraDeviceFactory : public CameraDeviceFactory
- {
- public:
- std::shared_ptr<CameraDevice> CreateCameraDevice() override
- {
- return std::make_shared<BaslerCameraDevice>();
- }
- };
-
- ReflectRegister("Basler", BaslerCameraDeviceFactory);
好了,现在回头再看客户端使用工厂方法模式创建对象的代码,就可以简化为:
- //运行时确定数组大小,且确定后不可改变
- auto camera_devices_ = std::make_unique<std::shared_ptr<CameraDevice>[]>(onlined_camera_num_);
-
- for(int i = 0; i < onlined_camera_num_; ++i)
- {
- auto p_factory = Object::CreateObject<CameraDeviceFactory>(camera_name[i]);//camera_name[i]中元素是提前获取的与连接的相机对应的供应商名称
- if (!p_factory)
- continue;
- else
- camera_devices_[i] = p_factory->CreateCameraDevice();
-
- delete p_factory;
- }
文章转载自:paw5zx