工厂模式
工厂模式分三种,从简单到复杂依次为:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式结构包括:工厂类、抽象产品类和具体产品类。
以一个工厂生产各种品牌的鞋为例,工厂单开一类,内设CreateShoes()函数,函数通过switch结构根据输入的鞋子类型名决定生产哪个牌子的鞋子;鞋子作为抽象产品类,覆盖了各个具体的鞋子牌子,细分到各个牌子的鞋子的模块则为具体产品类。
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 83
|
class Shoes { public: virtual ~Shoes() {} virtual void Show() = 0; };
class NikeShoes : public Shoes { public: void Show() { std::cout << "Nike's show" << std::endl; } };
class AdidasShoes : public Shoes { public: void Show() { std::cout << "Adidas's show" << std::endl; } };
enum SHOES_TYPE { NIKE, ADIDAS };
class ShoesFactory { public: Shoes* CreateShoes(SHOES_TYPE type) { switch (type) { case NIKE: return new NikeShoes(); break; case ADIDAS: return new AdidasShoes(); break; default: return nullptr; break; } } };
void main() { ShoesFactory shoesFactory;
Shoes* pNikeShoes = shoesFactory.CreateShoes(NIKE); if (pNikeShoes != nullptr) { pNikeShoes->Show(); delete pNikeShoes; pNikeShoes = nullptr; } Shoes* pAdidasShoes = shoesFactory.CreateShoes(ADIDAS); if (pAdidasShoes != nullptr) { pAdidasShoes->Show(); delete pAdidasShoes; pAdidasShoes = nullptr; } }
|
可以为各种不同牌子的鞋子开设独立的生产线,每个生产线只生产同品牌的鞋子,此时转为工厂方法模式。
工厂方法模式相比简单工厂模式,将工厂类分为抽象工厂类和具体工厂类,工厂和产品(鞋子)两块都有各自的抽象和具体。
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
| class FMShoes { public: virtual ~FMShoes() {} virtual void FMShow() = 0; };
class FMNikeShoes : public FMShoes { public: void FMShow() { std::cout << "Nike's show" << std::endl; } };
class FMAdidasShoes : public FMShoes { public: void FMShow() { std::cout << "Adidas's show" << std::endl; } };
class FMShoesFactory { public: virtual FMShoes* FMCreateShoes() = 0; virtual ~FMShoesFactory() {} };
class FMNikeProducer : public FMShoesFactory { public: FMShoes* FMCreateShoes() { return new FMNikeShoes(); } };
class FMAdidasProducer : public FMShoesFactory { public: FMShoes* FMCreateShoes() { return new FMAdidasShoes(); } };
|
当工厂与产品的生产关系不是一对一,而变成一对多时,比如原本只生产耐克鞋子的工厂现在生产耐克的各种产品,包括鞋子,衣服等,模式从工厂方法模式变为抽象工厂模式,不过四部分结构:抽象工厂类、具体工厂类、抽象产品类、具体产品类,仍然是这四部分。
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 83 84 85 86
| class AFShoes { public: virtual void AFShow() = 0; virtual ~AFShoes() {} };
class AFNikeShoes : public AFShoes { public: void AFShow() { std::cout << "nike shoes show" << std::endl; } };
class AFAdidasShoes : public AFShoes { public: void AFShow() { std::cout << "adidas shoes show" << std::endl; } };
class AFClothes { public: virtual ~AFClothes() {} virtual void AFShow() = 0; };
class AFNikeClothes : public AFClothes { public: void AFShow() { std::cout << "nike clothes show" << std::endl; } };
class AFAdidasClothes : public AFClothes { public: void AFShow() { std::cout << "adidas clothes show" << std::endl; } };
class AFFactory { public: virtual AFShoes* AFCreateShoes() = 0; virtual AFClothes* AFCreateClothes() = 0; virtual ~AFFactory() {} };
class AFNikeProducer : public AFFactory { public: AFShoes* AFCreateShoes() { return new AFNikeShoes(); }
AFClothes* AFCreateClothes() { return new AFNikeClothes(); } };
class AFAdidasProducer : public AFFactory { public: AFShoes* AFCreateShoes() { return new AFAdidasShoes(); }
AFClothes* AFCreateClothes() { return new AFAdidasClothes(); } };
|
进一步提高工厂类的封装性
以上三种方式在新增产品时,总要修改工厂类或新增具体的工厂类,怎样做到新增产品时不需要修改工厂类、不需要新增具体工厂类?
使用模板工厂,将工厂方法封装成模板工厂类。
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
| class TFShoes { public: virtual void TFShow() = 0; virtual ~TFShoes() {} };
class TFNikeShoes : public TFShoes { public: void TFShow() { std::cout << "nike shoes show" << std::endl; } };
class TFClothes { public: virtual void TFShow() = 0; virtual ~TFClothes() {} };
class TFUniqloClothes : public TFClothes { public: void TFShow() { std::cout << "uniqlo clothes show" << std::endl; } };
template<class TFAbstractProduct_t> class TFAbstractFactory { public: virtual TFAbstractProduct_t* TFCreateProduct() = 0; virtual ~TFAbstractFactory() {} };
template<class TFAbstractProduct_t, class TFConcreteProduct_t> class TFConcreteFactory : public TFAbstractFactory<TFAbstractProduct_t> { public: TFAbstractProduct_t* TFCreateProduct() { return new TFConcreteProduct_t(); } };
void main() { TFConcreteFactory<TFShoes, TFNikeShoes> nikeFactory; TFShoes* pNikeShoes = nikeFactory.TFCreateProduct(); pNikeShoes->TFShow(); delete pNikeShoes; pNikeShoes = NULL;
TFConcreteFactory<TFClothes, TFUniqloClothes> uniqloFactory; TFClothes* pUniqloClothes = uniqloFactory.TFCreateProduct(); pUniqloClothes->TFShow(); delete pUniqloClothes; pUniqloClothes = NULL; }
|
产品注册模板类+单例工厂模板类
模板工厂缺少一个可以统一随时随地获取指定的产品对象的类,解决办法是:可以把产品注册的对象用map保存,通过key-value方式获取对应的产品对象的实例。
思路:产品注册功能封装成注册模板类,注册的产品对象保存在工厂模板类的map,便于产品对象的获取。把获取产品对象的功能封装成工厂模板类,为了能随时随地获取指定的产品对象,把工厂设计成单例模式。
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| class PRShoes { public: virtual void PRShow() = 0; virtual ~PRShoes() {} };
class PRNikeShoes : public PRShoes { public: void PRShow() { std::cout << "NikeShoes show" << std::endl; } };
class PRClothe { public: virtual void PRShow() = 0; virtual ~PRClothe() {} };
class PRUniqlo : public PRClothe { public: void PRShow() { std::cout << "UniqloClothe show" << std::endl; } };
/*产品注册模板接口类*/ 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&); };
/*工厂模板类,用于获取和注册产品对象*/ template<class ProductType_t> class ProductFactory { public: /*工厂单例的实现是使用static搭配private的构造和析构函数*/ 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; } /*获取产品对象,通过“名字”找到对应的“注册员”,来产生产品*/ ProductType_t* GetProduct(std::string name) { 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&); std::map<std::string, IProductRegistrar<ProductType_t>*> m_ProductRegistry; };
/*产品注册模板类,用于创建具体的产品和从工厂里注册产品*/ template<class ProductType_t, class ProductImpl_t> class ProductRegistrar : public IProductRegistrar<ProductType_t> { public: /*构造函数,explicit使得其只能显式调用,必须要提供name,不提供名字我怎么知道自己要注册什么产品?*/ explicit ProductRegistrar(std::string name) { /*用(大种类ProductType_t)相应工厂的实例去注册map*/ ProductFactory<ProductType_t>::Instance().RegisterProduct(this, name); } /*产生一个具体产品,返回其指针*/ ProductType_t* CreateProduct() { return new ProductImpl_t(); } };
void main() { /*生产nike鞋的过程*/ /*注册产品的种类(大类)为PRShoes,产品(子类)为PRNikeShoes,产品名为nike(通过显式调用)*/ ProductRegistrar<PRShoes, PRNikeShoes> nikeShoes("nike"); /*从PRShoes工厂单例中获取nike产品对象*/ PRShoes* pNikeShoes = ProductFactory<PRShoes>::Instance().GetProduct("nike"); pNikeShoes->PRShow(); if(pNikeShoes) { delete pNikeShoes; } }
|