建议直接空降至参考文献,点击链接
简单工厂模式
#include<iostream> using namespace std; class BasicCamera { public: virtual ~BasicCamera() {}; virtual void OpenCamera() = 0; }; class Hik :public BasicCamera { public: void OpenCamera() { cout << "打开海康相机" << endl; } }; class DaHua :public BasicCamera { public: void OpenCamera() { cout << "打开大华相机" << endl; } }; class Factory { public: BasicCamera* CreateCamera(string type) { if (type == "Hik") return new Hik(); else if (type == "DaHua") return new DaHua(); else return NULL; } }; int main() { Factory fac = Factory(); BasicCamera* camera = fac.CreateCamera("Hik"); camera->OpenCamera(); delete camera; getchar(); return 0; }当我们需要增加一类相机时,我们需要先定义一个类继承BasicCamera类,还要修改 Factory 类的代码,增加if else判断。这显然是违背开闭原则的。
Tips:
1. 由于工厂模式会返回一个基类指针,指向新生成的derived类对象,对象位于heap,为避免泄露内存和其他资源,要将返回的对象delete掉。如果前面的基类(BasicCamera)没有virtual的析构函数,那么通常发生的是对象的derived部分没有被销毁,产生局部销毁的现象。因此必须要加
virtual ~BasicCamera() {};
2. 基类生成对象不合理,因此在基类中定义了纯虚函数
virtual void OpenCamera() = 0;
3. UML图
+表示public,函数后面加冒号后面跟着返回类型。
工厂方法模式
#include<iostream> using namespace std; class BasicCamera { public: virtual ~BasicCamera() {}; virtual void OpenCamera() = 0; }; class Hik :public BasicCamera { public: void OpenCamera() { cout << "打开海康相机" << endl; } }; class DaHua :public BasicCamera { public: void OpenCamera() { cout << "打开大华相机" << endl; } }; class Factory { public: virtual ~Factory() {} virtual BasicCamera* CreateCamera() = 0; }; class HikFactory :public Factory { BasicCamera* CreateCamera() { return new Hik(); } }; class DaHuaFactory :public Factory { DaHua* CreateCamera() { return new DaHua(); } }; int main() { Factory* fac = new HikFactory(); BasicCamera* cam = fac->CreateCamera(); cam->OpenCamera(); delete cam; delete fac; getchar(); return 0; }
在以下情况下可以使用工厂方法模式:
- 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
- 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
抽象工厂模式
#include<iostream> using namespace std; class BasicCamera { public: virtual ~BasicCamera() {}; virtual void OpenCamera() = 0; }; class HikCamera :public BasicCamera { public: void OpenCamera() { cout << "打开海康相机" << endl; } }; class BasicLen { public: virtual ~BasicLen() {}; virtual void InstallLen() = 0; }; class HikLen :public BasicLen { void InstallLen() { cout << "安装了海康镜头" << endl; } }; class Factory { public: virtual ~Factory() {}; virtual BasicCamera* CreateCamera() = 0; virtual BasicLen* CreateLen() = 0; }; class HikFactory :public Factory { BasicCamera* CreateCamera() { return new HikCamera(); } BasicLen* CreateLen() { return new HikLen(); } }; int main() { Factory* fac = new HikFactory(); BasicCamera* cam = fac->CreateCamera(); BasicLen* len = fac->CreateLen(); cam->OpenCamera(); len->InstallLen(); delete len; delete cam; delete fac; getchar(); return 0; }
优点:
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
抽象模板工厂
#include<iostream> using namespace std; class BasicCamera { public: virtual ~BasicCamera() {}; virtual void OpenCamera() = 0; }; class HikCamera :public BasicCamera { public: void OpenCamera() { cout << "打开海康相机" << endl; } }; class DaHuaCamera :public BasicCamera { public: void OpenCamera() { cout << "打开大华相机" << endl; } }; class BasicLen { public: virtual ~BasicLen() {}; virtual void InstallLen() = 0; }; class HikLen :public BasicLen { void InstallLen() { cout << "安装了海康镜头" << endl; } }; template <class AbstractProduct_t> class AbstractFactory { public: virtual ~AbstractFactory() {}; virtual AbstractProduct_t* CreateProduct() = 0; }; template <class AbstractProduct_t, class ConcreteProduct_t> class ConcreteFactory :public AbstractFactory< AbstractProduct_t> { public: AbstractProduct_t* CreateProduct() { return new ConcreteProduct_t(); } }; int main() { AbstractFactory<BasicCamera>* fac = new ConcreteFactory<BasicCamera, HikCamera>(); AbstractFactory<BasicCamera>* fac1 = new ConcreteFactory<BasicCamera, DaHuaCamera>(); AbstractFactory<BasicLen>* fac2 = new ConcreteFactory<BasicLen, HikLen>(); BasicCamera* cam = fac->CreateProduct(); BasicCamera* cam1 = fac1->CreateProduct(); BasicLen* len = fac2->CreateProduct(); cam->OpenCamera(); cam1->OpenCamera(); len->InstallLen(); delete cam,cam1,len,fac,fac1,fac2; getchar(); return 0; }
产品注册模板类+单例工厂模板类
#include<iostream> #include <map> using namespace std; class BasicCamera { public: virtual ~BasicCamera() {}; virtual void OpenCamera() = 0; }; class HikCamera :public BasicCamera { public: void OpenCamera() { cout << "打开海康相机" << endl; } }; class DaHuaCamera :public BasicCamera { public: void OpenCamera() { cout << "打开大华相机" << endl; } }; class BasicLen { public: virtual ~BasicLen() {}; virtual void InstallLen() = 0; }; class HikLen :public BasicLen { void InstallLen() { cout << "安装了海康镜头" << endl; } }; // 基类,产品注册模板接口类 // 模板参数 ProductType_t 表示的类是产品抽象类 template <class ProductType_t> class IProductRegistrar { public: // 获取产品对象抽象接口 virtual ProductType_t* CreateProduct() = 0; protected: // 禁止外部构造和虚构, 子类的"内部"的其他函数可以调用 IProductRegistrar() {} virtual ~IProductRegistrar() {} private: // 禁止外部拷贝和赋值操作 IProductRegistrar(const IProductRegistrar&); const IProductRegistrar& operator=(const IProductRegistrar&); }; // 工厂模板类,用于获取和注册产品对象 // 模板参数 ProductType_t 表示的类是产品抽象类 template <class ProductType_t> class ProductFactory { public: // 获取工厂单例,工厂的实例是唯一的 static ProductFactory<ProductType_t>& Instance() { static ProductFactory<ProductType_t> instance; return instance; } // 产品注册 void RegisterProduct(IProductRegistrar<ProductType_t>* registrar, std::string name) { m_ProductRegistry[name] = registrar; } // 根据名字name,获取对应具体的产品对象 ProductType_t* GetProduct(std::string name) { // 从map找到已经注册过的产品,并返回产品对象 if (m_ProductRegistry.find(name) != m_ProductRegistry.end()) { return m_ProductRegistry[name]->CreateProduct(); } // 未注册的产品,则报错未找到 std::cout << "No product found for " << name << std::endl; return NULL; } private: // 禁止外部构造和虚构 ProductFactory() {} ~ProductFactory() {} // 禁止外部拷贝和赋值操作 ProductFactory(const ProductFactory&); const ProductFactory& operator=(const ProductFactory&); // 保存注册过的产品,key:产品名字 , value:产品类型 map<string, IProductRegistrar<ProductType_t>*> m_ProductRegistry; }; // 产品注册模板类,用于创建具体产品和从工厂里注册产品 // 模板参数 ProductType_t 表示的类是产品抽象类(基类),ProductImpl_t 表示的类是具体产品(产品种类的子类) template <class ProductType_t, class ProductImpl_t> class ProductRegistrar : public IProductRegistrar<ProductType_t> { public: // 构造函数,用于注册产品到工厂,只能显示调用 explicit ProductRegistrar(std::string name) { // 通过工厂单例把产品注册到工厂 ProductFactory<ProductType_t>::Instance().RegisterProduct(this, name); } // 创建具体产品对象指针 ProductType_t* CreateProduct() { return new ProductImpl_t(); } }; int main() { IProductRegistrar<BasicCamera>* reg = new ProductRegistrar<BasicCamera, HikCamera>("camera_Hik"); BasicCamera* cam = ProductFactory<BasicCamera>::Instance().GetProduct("camera_Hik"); cam->OpenCamera(); if (cam) delete cam; getchar(); return 0; }
产品注册的对象用std::map
的方式保存,通过key-valve
的方式可以轻松简单的获取对应的产品对象实例。
Tips:(未完成)
1. Instance
单例模式
2. map
map是STL的一个关联容器,它提供一对一的hash
- 第一个可以称为关键字(key),每个关键字只能在map中出现一次;
- 第二个可能称为该关键字的值(value);
参考文献
https://www.cnblogs.com/xiaolincoding/p/11524376.html
https://www.cnblogs.com/xiaolincoding/p/11524401.html
https://www.zhihu.com/question/20367734/answer/1089721250