前言
前一篇文章 介绍了简单工厂模式,提到了简单工厂模式的缺点(违反开闭原则,扩展困难),本文要介绍的工厂方法模式在一定程度上弥补了简单工厂模式的缺点。
工厂方法模式
简介
工厂方法模式是创建型设计模式之一,它在抽象工厂类中声明创建对象的接口,在具体工厂类中实现具体的实例化过程。这个模式的核心思想是将对象的实例化延迟到子类中进行。
这样的话,当要添加一个具体产品时,我们不会修改原有的工厂类(对修改封闭),而是新创建一个关联于具体产品的具体工厂类(对扩展开放)。
示例
抽象相机类:CameraDevice
具体相机类:BaslerCameraDevice,SickCameraDevice,HuarayCameraDevice
抽象工厂类:CameraDeviceFactory
具体工厂类:BaslerCameraFactory,SickCameraFactory,HuarayCameraFactory
UML类图如下:
代码如下:
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| class CameraDevice { public: CameraDevice() = default; virtual ~CameraDevice() = 0; virtual bool Init(){}; virtual bool OpenDevice() = 0; };
class BaslerCameraDevice : public CameraDevice { public: ~BaslerCameraDevice() override{} bool Init() override{} bool OpenDevice() override{} };
class HuarayCameraDevice : public CameraDevice { public: ~HuarayCameraDevice() override{} bool Init() override{} bool OpenDevice() override{} };
class SickCameraDevice : public CameraDevice { public: ~SickCameraDevice() override{} bool Init() override{} bool OpenDevice() override{} };
class CameraDeviceFactory { public: virtual std::shared_ptr<CameraDevice> CreateCamera() = 0; };
class BaslerCameraFactory : public CameraDeviceFactory { public: std::shared_ptr<CameraDevice> CreateCamera() override { return std::make_shared<BaslerCameraDevice>(); } };
class HuarayCameraFactory : public CameraDeviceFactory { public: std::shared_ptr<CameraDevice> CreateCamera() override { return std::make_shared<HuarayCameraDevice>(); } };
class SickCameraFactory : public CameraDeviceFactory { public: std::shared_ptr<CameraDevice> CreateCamera() override { return std::make_shared<SickCameraDevice>(); } };
int main(int argc, char* argv[]) {
std::shared_ptr<CameraDeviceFactory> factory = std::make_shared<BaslerCameraFactory>(); std::shared_ptr<CameraDevice> camera = factory->CreateCamera(); camera->Init(); camera->OpenDevice();
return 0; }
|
优点
- 解耦:工厂方法模式可以减少客户代码与具体类之间的耦合。客户端在使用的时候只需知道接口,而不是具体类。这样可以更容易地扩展或修改创建逻辑,而无需修改现有客户代码。
- 符合开闭原则:工厂方法模式允许提供方在不修改现有代码的情况下引入新的类型。满足对扩展开放,对修改封闭的原则。
- 单一职责原则:工厂方法模式中,创建对象的逻辑被封装在一个工厂类中,这符合单一职责原则。这让代码更加清晰,维护也更简单。
缺点
- 代码复杂:工厂方法模式为每种产品类型提供一个单独的工厂类。这意味着每增加一个新的产品类别,就需要增加一个新的具体工厂类。这会导致类的数量迅速增加,从而增加了代码的复杂性
- 代码冗余:如果具体工厂类之间的创建逻辑相似,这可能会导致代码冗余。虽然每个工厂类只负责创建一个具体产品,但这些工厂类的创建逻辑可能高度相似,不能有效地重用代码。
- 客户端违反开闭原则:虽然工厂方法模式使提供方代码遵守了开闭原则,但是在客户端,仍需根据传入的参数决定具体实例化哪一个类,选择判断的问题仍存在。即工厂方法模式把提供方简单工厂类的内部判断逻辑转移到了客户端代码,这让客户端代码违反了开闭原则。
使用场景
- 产品类别经常变化:一个系统会频繁添加或修改产品的创建,而每种产品的创建又有不同的复杂配置和依赖时,工厂方法可以将具体产品的创建逻辑封装在各自的工厂类中,从而简化客户端代码。
参考文章
1.《大话设计模式》