赞
踩
工厂模式定义:这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式、在工厂模式中,我们在创建对对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单来说,使用了c++多态的特性,将存在继承关系的类,通过一个工厂类创建对应的子类(派生类)对象。在项目复杂的情况下,可以便于子类对象的创建。
工厂模式的实现方式可分为简单工厂模式、工厂方法模式、抽象工厂模式,每个实现方式都存在优和劣。
具体的情况:
鞋厂可以指定生成耐克、阿迪达斯和李宁牌子的鞋子。哪个鞋炒的火爆,老板就生产哪个,看形势生产。
UML图:
简单工厂模式的结构组成:
简单工厂模式的特点:
简单工厂模式的缺陷:
简单工厂模式的代码:
- #include <iostream>
-
- class Shoes {
- public:
- virtual ~Shoes() {};
- virtual void Show() = 0;
- };
-
- class NiKeShoes : public Shoes {
- void Show()
- {
- std::cout << "我是耐克,我的广告语:Just do it" << std::endl;
- }
- };
-
- class AdidasShoes : public Shoes {
- void Show()
- {
- std::cout << "我是阿迪达斯,我的广告语:Impossible is nothing" << std::endl;
- }
- };
-
- class LiNingShoes : public Shoes {
- void Show()
- {
- std::cout << "我是李宁,我的广告语:Everything is possible" << std::endl;
- }
- };
-
- enum SHOES_TYPE
- {
- NIKE,
- LINING,
- ADIDAS
- };
-
- class ShoesFactory{
- public:
- Shoes* CreateShoes(SHOES_TYPE type);
- };
-
- Shoes* ShoesFactory::CreateShoes(SHOES_TYPE type)
- {
- switch (type)
- {
- case NIKE:
- return new NiKeShoes();
- break;
- case LINING:
- return new LiNingShoes();
- break;
- case ADIDAS:
- return new AdidasShoes();
- break;
- default:
- return NULL;
- break;
- }
- }
-
- int main()
- {
- //构造工厂对象
- ShoesFactory shoesFactory;
-
- //从鞋厂对象创建耐克对象
- Shoes* pNikeShoes = shoesFactory.CreateShoes(NIKE);
- if (pNikeShoes != NULL)
- {
- //耐克广告喊起
- pNikeShoes->Show();
- //释放资源
- delete pNikeShoes;
- pNikeShoes = NULL;
- }
-
- //从鞋厂对象创建李宁对象
- Shoes* pLiNingShoes = shoesFactory.CreateShoes(LINING);
- if (pLiNingShoes != NULL)
- {
- //李宁广告喊起
- pLiNingShoes->Show();
- //释放资源
- delete pLiNingShoes;
- pLiNingShoes = NULL;
- }
-
- //从鞋厂对象创建阿迪达斯对象
- Shoes* pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
- if (pAdidasShoes != NULL)
- {
- //阿迪达斯广告喊起
- pAdidasShoes->Show();
- //释放资源
- delete pAdidasShoes;
- pAdidasShoes = NULL;
- }
-
- return 0;
- }
具体情形:
UML图:
工厂方法模式的结构组成:
工厂方法模式的特点:
工厂方法模式的缺陷:
工厂方法模式的代码:
- #include <iostream>
-
- class Shoes {
- public:
- virtual ~Shoes() {};
- virtual void Show() = 0;
- };
-
- class NiKeShoes : public Shoes {
- void Show()
- {
- std::cout << "我是耐克,我的广告语:Just do it" << std::endl;
- }
- };
-
- class AdidasShoes : public Shoes {
- void Show()
- {
- std::cout << "我是阿迪达斯,我的广告语:Impossible is nothing" << std::endl;
- }
- };
-
- class LiNingShoes : public Shoes {
- void Show()
- {
- std::cout << "我是李宁,我的广告语:Everything is possible" << std::endl;
- }
- };
-
-
- class ShoesFactory {
- public:
- virtual Shoes* CreateShoes() = 0;
- virtual ~ShoesFactory() {};
- };
- //耐克生成者/生产链
- class NiKeProducer : public ShoesFactory{
- public:
- Shoes* CreateShoes() {
- return new NiKeShoes();
- }
- };
- //阿迪达斯生成者/生产链
- class AdidasProducer : public ShoesFactory {
- public:
- Shoes* CreateShoes() {
- return new AdidasShoes();
- }
- };
- //李宁生成者/生产链
- class LiNingProducer : public ShoesFactory {
- public:
- Shoes* CreateShoes() {
- return new LiNingShoes();
- }
- };
-
- int main()
- {
- // ==================== 生产耐克流程 ================= //
- //鞋厂开设耐克生产线
- ShoesFactory* niKeProducer = new NiKeProducer();
- //耐克生产线产出球鞋
- Shoes* nikeShoes = niKeProducer->CreateShoes();
- //耐克球鞋喊起
- nikeShoes->Show();
- //释放资源
- delete niKeProducer;
- delete nikeShoes;
- // ==================== 生产阿迪达斯流程 ================= //
- //鞋厂开设阿迪达斯生产线
- ShoesFactory* adidasProducer = new AdidasProducer();
- //阿迪达斯生产线产出球鞋
- Shoes* adidasShoes = adidasProducer->CreateShoes();
- //阿迪达斯球鞋喊起
- adidasShoes->Show();
- //释放资源
- delete adidasProducer;
- delete adidasShoes;
- // ==================== 生产李宁流程 ================= //
- //鞋厂开设李宁生产线
- ShoesFactory* liNingProducer = new LiNingProducer();
- //李宁生产线产出球鞋
- Shoes* liNingShoes = liNingProducer->CreateShoes();
- //李宁球鞋喊起
- liNingShoes->Show();
- //释放资源
- delete liNingProducer;
- delete liNingShoes;
-
- return 0;
- }
具体情形:
UML图:
抽象工厂模式的结构组成(和工厂方法模式一样)
抽象工厂模式的特点:
抽象工厂模式的缺点:
抽象工厂的代码:
- #include <iostream>
-
- class Shoes {
- public:
- virtual ~Shoes() {};
- virtual void Show() = 0;
- };
-
- class NiKeShoes : public Shoes {
- public:
- void Show()
- {
- std::cout << "我是耐克鞋,让你酷起来" << std::endl;
- }
- };
- class Clothe {
- public:
- virtual ~Clothe() {};
- virtual void Show() = 0;
- };
-
- class NiKeClothe : public Clothe {
- public:
- void Show()
- {
- std::cout << "我是耐克衣服,时尚我最在行!" << std::endl;
- }
- };
- //总厂
- class Factory {
- public:
- virtual Shoes* CreateShoes() = 0;
- virtual Clothe* CreateClothe() = 0;
- virtual ~Factory() {};
- };
- //耐克生成者/生产链
- class NiKeProducer : public Factory {
- public:
- Shoes* CreateShoes() {
- return new NiKeShoes();
- }
-
- Clothe* CreateClothe() {
- return new NiKeClothe();
- }
- };
-
- int main()
- {
- // ==================== 生产耐克流程 ================= //
- //鞋厂开设耐克生产线
- NiKeProducer* niKeProducer = new NiKeProducer();
- //耐克生产线产出球鞋
- Shoes* nikeShoes = niKeProducer->CreateShoes();
- //耐克生产线产出衣服
- Clothe* nikeClothe = niKeProducer->CreateClothe();
-
- //耐克球鞋喊起
- nikeShoes->Show();
- //耐克衣服广告喊起
- nikeClothe->Show();
- //释放资源
- delete niKeProducer;
- delete nikeShoes;
- delete nikeClothe;
-
- return 0;
- }
以上三种工厂模式,在新增产品时,都存在一定的缺陷。
那么有什么好的方法,在新增产品时,即不用修改工厂类,也不用新增具体的工厂类?
针对工厂方法模式封装成模版工厂类,那么这样在新增产品时,是不需要新增具体的工厂类,减少了代码的编写量。
UML图:
模板工厂代码:
- #include <iostream>
- //基类鞋子
- class Shoes {
- public:
- virtual ~Shoes() {};
- virtual void Show() = 0;
- };
- //基类衣服
- class Clothe {
- public:
- virtual ~Clothe() {};
- virtual void Show() = 0;
- };
- //耐克鞋子
- class NiKeShoes :public Shoes {
- public:
- void Show() {
- std::cout << "我是耐克球鞋,我的广告语:Just do it" << std::endl;
- }
- };
- //耐克衣服
- class UniqloClothe :public Clothe {
- public:
- void Show() {
- std::cout << "我是优衣库衣服,我的广告语:I am Uniqlo" << std::endl;
- }
- };
-
- //抽象模版工厂类
- //模板参数:AbstractProduct_t 产品抽象类
- template <class Abstractproduct_t>
- class AbstractFactoy
- {
- public:
- virtual Abstractproduct_t* CreateProduct() = 0;
- virtual ~AbstractFactoy() {};
- };
- //具体模板工厂类
- template <class AbstractProduct_t,class ConcreteProduct_t>
- class ConcreteFactory :public AbstractFactoy<AbstractProduct_t>
- {
- public:
- AbstractProduct_t* CreateProduct()
- {
- return new ConcreteProduct_t();
- }
- };
-
- int main()
- {
- //构建耐克鞋的工厂对象
- ConcreteFactory<Shoes, NiKeShoes> nikeFactory;
- //创建耐克鞋对象
- Shoes* pNiKeShoes = nikeFactory.CreateProduct();
- //打印耐克鞋广告语
- pNiKeShoes->Show();
-
- //构建优衣库的工厂对象
- ConcreteFactory<Clothe, UniqloClothe> uniqloFactory;
- //创建优衣库对象
- Clothe* pUniqloClothe = uniqloFactory.CreateProduct();
- //打印优衣库广告语
- pUniqloClothe->Show();
-
- delete pNiKeShoes;
- pNiKeShoes = NULL;
-
- delete pUniqloClothe;
- pUniqloClothe = NULL;
-
- return 0;
- }
前面的模板工厂虽然在新增产品的时候,不需要新增具体的工厂类,但是缺少一个可以统一随时随地获取指定的产品对象的类。
还有改进的空间,我们可以把产品注册的对象用std::map的方式保存,通过key-value的方式可以轻松简单的获取对应的产品对象实例。
实现的思路:
UML图:
产品注册模板类+单例工厂模板类
- #include <iostream>
- #include <map>
- //基类鞋子
- class Shoes {
- public:
- virtual ~Shoes() {};
- virtual void Show() = 0;
- };
- //基类衣服
- class Clothe {
- public:
- virtual ~Clothe() {};
- virtual void Show() = 0;
- };
- //耐克鞋子
- class NiKeShoes :public Shoes {
- public:
- void Show() {
- std::cout << "我是耐克球鞋,我的广告语:Just do it" << std::endl;
- }
- };
- //耐克衣服
- class UniqloClothe :public Clothe {
- public:
- void Show() {
- std::cout << "我是优衣库衣服,我的广告语:I am Uniqlo" << std::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:产品类型
- std::map<std::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) //explicit 防止隐形类型转换
- {
- //通过工厂单例把产品注册到工厂
- ProductFactory<ProductType_t>::instance().RegisterProduct(this, name);
- }
-
- // 创建具体产品对象指针
- ProductType_t* CreateProduct()
- {
- return new ProductImpl_t();
- }
-
- };
- int main()
- {
- // ============== 生产耐克球鞋过程 ================= //
- // 注册产品种类为Shoes(基类),产品为NiKe(子类)到工厂,产品名为nike
- ProductRegistrar <Shoes, NiKeShoes> nikeShoes("nike");
- //从工厂获取产品种类为Shoes,名称为nike的产品对象
- Shoes* pNiKeShoes = ProductFactory<Shoes>::instance().GetProduct("nike");
- //显示产品的广告语
- pNiKeShoes->Show();
- // 释放资源
- if (pNiKeShoes)
- {
- delete pNiKeShoes;
- }
-
- // ============== 生产耐克球鞋过程 ================= //
- // 注册产品种类为Clothe(基类),产品为UniqloClothe(子类)到工厂,产品名为uniqlo
- ProductRegistrar <Clothe, UniqloClothe> uniqloClothe("uniqlo");
- //从工厂获取产品种类为Shoes,名称为nike的产品对象
- Clothe* pUniqloClothe = ProductFactory<Clothe>::instance().GetProduct("uniqlo");
- //显示产品的广告语
- pUniqloClothe->Show();
- // 释放资源
- if (pUniqloClothe)
- {
- delete pUniqloClothe;
- }
-
- return 0;
- }
总结:
将工厂方法模式改良成模板工厂,虽然可以解决产品新增时,不需要新增具体工厂类,但是缺少一个可以随时随地获取产品对象的方式,说明还有改进的空间。
将模板工厂改良成产品注册模板类+单例工厂模板类,产品注册模板类用于注册不同类型的产品,单例工厂模板类用于获取指定已注册的产品对象。这种方式,可以把工厂模式中产品的注册和获取的主要功能很好的抽象成两个类,并且使用单例模式使得工厂类可以随时随地获取已注册的产品对象。
所以产品注册模板类+单例模板类的工厂模式,达到了开闭法则,并且扩展性高和封装度高。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。