设计模式学习(二)工厂模式——抽象工厂模式+注册表
前言
在上一篇文章中 我们提到了抽象工厂模式初版代码的一些缺点:①客户端违反开闭原则②提供方违反开闭原则。本文将针对这两点进行讨论
使用简单工厂改进
对于缺点①,我们可以使用简单工厂的思路来改进抽象工厂的初版代码。对于上一篇文章中的例子,我们去除CameraFactory
、BaslerCameraFactory
和SickCameraFactory
,取而代之的是SimpleFactory
类。
类图如下:
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class SimpleFactory { public: BaslerCamera* CreateBaslerCamera() { if ("Linux" == os_name_) { return new LinuxBaslerCamera(); } else if ("Windows" == os_name_) { return new WindowsBaslerCamera(); } else { return nullptr; } }
SickCamera* CreateSickCamera() { if ("Linux" == os_name_) { return new LinuxSickCamera(); } else if ("Windows" == os_name_) { return new WindowsSickCamera(); } else { return nullptr; } } public: std::string os_name_ = "Linux";
};
int main() { SimpleFactory* camera_factory = new SimpleFactory(); BaslerCamera* basler_camera = camera_factory->CreateBaslerCamera(); basler_camera->OpenCamera();
SickCamera* sick_camera = camera_factory->CreateSickCamera(); sick_camera->OpenCamera();
return 0; }
|
注意,上述方法虽然改进了缺点①,但是缺点②仍存在。
使用注册表改进
对于缺点②,其本质是:增加新产品时,对工厂类带来的修改违反了开闭原则。对于这种情况,我们可以参考《设计模式学习(二)工厂模式——工厂方法模式+注册表》 中提到的注册表,来去除switch
或if
这种分支判断,解除分支判断带来的耦合。
对于具体产品,我们可以这样将它注册:
1 2 3 4 5 6 7 8 9 10 11
| class LinuxBaslerCamera : public BaslerCamera { public: ~LinuxBaslerCamera() override = default; bool OpenCamera() override { return true; } };
ReflectRegister("LinuxBasler", LinuxBaslerCamera);
|
然后工厂类的代码可以简化为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class SimpleFactory { public: BaslerCamera* CreateBaslerCamera() { std::string name = os_name_ + "Basler"; return Object::CreateObject<BaslerCamera>(name); }
SickCamera* CreateSickCamera() { std::string name = os_name_ + "Sick"; return Object::CreateObject<SickCamera>(name); } public: std::string os_name_ = "Linux"; };
|
这样,在产品族增加时(比如增加一个HarmonyOS
),我们只需要在它下面的产品类对应的文件中使用ReflectRegister
注册,然后改变os_name_
即可(当然os_name_
也可以在运行时从配置文件中加载,这样更好)。
而对于现有的产品族内增加新产品(比如增加一个Huaray
相机),工厂类中还是要增加一个CreateHuarayCamera
函数。
参考文章
1.《大话设计模式》