设计模式之工厂模式

来源:互联网 发布:美国最新数据公布 编辑:程序博客网 时间:2024/05/18 10:35

1、什么是工厂模式:
工厂模式就是为类实例的创建提供过渡接口,将复杂的对象创建过程封装、屏蔽起来,达到提高灵活性的目的。可以看下面一个简单的例子:如果我们有大众和通用两种品牌的车,都派生于一个基类“car”,两种车有各自的一些特性(类成员),那么在创建他们时就要做不同的初始化工作,为了方便的生产这两种车,建立了一个工厂,该工厂可以根据客户提供的品牌代码与车型代码去生产这些车辆(factory的create方法)。。。

//------------------------------------------------// a simple example of factory paradigm// base class: car // Derived Class: dasAutoCar & GMCar// factory class: carFactory//------------------------------------------------#include <iostream>#include <string>using namespace std;// -- base classclass car{    public: //      car(string str):brandName(str){};     virtual ~car(){};  // 汽车类,基类,将析构函数定义为虚函数     string getBrandName(){return brandName;};private:    string brandName;};// drive classclass dasAutoCar: public car{     //…… 细节并不重要    int code;    public:        dasAutoCar(int carCode):car(string("dasAuto")),code(carCode){};};// drive classclass GMCar: public car{    int code;    public:        GMCar():car(string("dasAuto")){};};// factory classclass carFactory{    public:        car* create(int brandCode, int carCode=0) // 构造函数的参数为品牌代码        {            switch(brandCode)            {                case 1:  // 如果品牌代码为1, 生产一辆大众车                    return new dasAutoCar(carCode);                    break;                case 2:  // 如果品牌代码为2,生产一辆通用车                    return new GMCar();                    break;                default:                    return 0;            }        }};// main function: test above codevoid main(){    carFactory cf;    car* myCar = cf.create(1,001); //生产了一辆大众车    cout<<myCar->getBrandName()<<endl;       delete myCar; //注意,这里没有delete会内存泄漏啊}

上例实际上是工场模式的第一种形式:简单工厂模式
工厂模式有根据其抽象层次与实现方法的不同分为:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式

2、为什么要用工厂模式:
工厂模式的最大目的就是希望降低耦合,客户只需要告知工厂,需要什么样的产品,而不需要知道产品的具体实现过程。
另外,effective c++告诉我们,在使用工厂模式的情况下,可以直接使用智能指针来管理产生的产品,避免造成内存泄漏:

3、工厂模式的三种实现方式及其各自的优劣:

ok,感觉自己有点学的不深刻,还是继续以“汽车”为例,写一下工程模式的三种实现吧:

第一: 简单工厂模式

#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>   // 和内存泄漏检测相关的头文件#include <iostream>#include <memory>  // 引入智能指针的头文件,VS2010环境using namespace std;// base class: carclass car{public:    string brand;  //汽车的品牌    car(string brd):brand(brd){};    virtual ~car(){};  //注意,将基类的析构函数定义为虚函数};class BwmCar: public car{public:    BwmCar(string brd,int codes): car(brd),code(codes){cout<<"a BWM car was build!"<<endl;};private:    /* 一些宝马车的特殊参数*/    int code;};class BenzCar: public car{public:    BenzCar(string brd, int codes): car(brd),code(codes)    {        cout<<"a benz car was build!"<<endl;    };private: /* 一些奔驰车的特殊参数 */    int code;};class factory{public:    car* createCar(int brandNum)    {        switch(brandNum)        {        case 1:            return new BwmCar("BWM",0);            break;        case 2:            return new BenzCar("Benz", 0);            break;        default:            return 0; //return a NULL pointer            break;        }    }};int main(){    factory f;    {        shared_ptr<car> pCar(f.createCar(1));        //car* pCar = f.createCar(2);    }    _CrtDumpMemoryLeaks();    return 0;}

上述就是第一类(简单工厂模式的典型实现),将一些产品的实现过程封装在一个工程类中,将产品的实现过程隐藏起来,而用户只需要将能标志产品类别的参数传递给工厂中的create方法就可以获得所需的产品。
这样做有什么好处呢?封装复杂的产品实现过程!案例中产品的生产过程很简单,直接new就好了,但是实际上,有时候一个产品的构造函数可能需要很多的参数,而这些参数可能需要通过一系列的计算才能得到,在多线程的程序中还可能涉及到一些同步问题,如果把这些程序段都放在主程序中会使得代码过于臃肿。

第二:工厂方法模式
对于简单工厂模式,一个工厂会生产各种各样的产品,每增加一个新的产品都需要重新修改工产类,对用户而言,很麻烦,不是吗?如果你也这样认为,请使用工厂方法模式:

class factory{public:    virtual car* createCar(int brandNum) =0; //pure virtual};class BwmFac: public factory{public:    virtual car* createCar(){return new BwmCar("BWM",0);}};class BenzFac: public factory{public:    virtual car* createCar(){return new BenzCar("Benz",0);}};

这样一个工厂就生产一种产品了,希望生产出哪种产品就先建立一个对应的工厂,并通过工厂去产生产品!!!
如果客户需要多一种产品,也无需修改原有的工厂类,再建一个新的就是咯!!!
当然,如果产品很多呢?例如,宝马有很多型号的车啊,当然,奔驰也有,一个车型一个工厂是不是好浪费,那请使用抽象工厂模式。。。

第三:抽象工厂模式:

/*** FileName   : AbstractFactoryPatternDemo** Author    : Jelly Young** Date     : 2013/11/19** Description : More information*/#include <iostream>using namespace std;// Product Aclass ProductA{public:  virtual void Show() = 0;};class ProductA1 : public ProductA{public:  void Show()  {    cout<<"I'm ProductA1"<<endl;  }};class ProductA2 : public ProductA{public:  void Show()  {    cout<<"I'm ProductA2"<<endl;  }};// Product Bclass ProductB{public:  virtual void Show() = 0;};class ProductB1 : public ProductB{public:  void Show()  {    cout<<"I'm ProductB1"<<endl;  }};class ProductB2 : public ProductB{public:  void Show()  {    cout<<"I'm ProductB2"<<endl;  }};// Factoryclass Factory{public:  virtual ProductA *CreateProductA() = 0;  virtual ProductB *CreateProductB() = 0;};class Factory1 : public Factory{public:  ProductA *CreateProductA()  {    return new ProductA1();  }  ProductB *CreateProductB()  {    return new ProductB1();  }};class Factory2 : public Factory{  ProductA *CreateProductA()  {    return new ProductA2();  }  ProductB *CreateProductB()  {    return new ProductB2();  }};int main(int argc, char *argv[]){  Factory *factoryObj1 = new Factory1();  ProductA *productObjA1 = factoryObj1->CreateProductA();  ProductB *productObjB1 = factoryObj1->CreateProductB();  productObjA1->Show();  productObjB1->Show();  Factory *factoryObj2 = new Factory2();  ProductA *productObjA2 = factoryObj2->CreateProductA();  ProductB *productObjB2 = factoryObj2->CreateProductB();  productObjA2->Show();  productObjB2->Show();  if (factoryObj1 != NULL)  {    delete factoryObj1;    factoryObj1 = NULL;  }  if (productObjA1 != NULL)  {    delete productObjA1;    productObjA1= NULL;  }  if (productObjB1 != NULL)  {    delete productObjB1;    productObjB1 = NULL;  }  if (factoryObj2 != NULL)  {    delete factoryObj2;    factoryObj2 = NULL;  }  if (productObjA2 != NULL)  {    delete productObjA2;    productObjA2 = NULL;  }  if (productObjB2 != NULL)  {    delete productObjB2;    productObjB2 = NULL;  }}

======================================================
未完,待续。
2016.10.26

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 6s p换屏幕原装太贵怎么办 4g手机开不开机黑屏怎么办 华为麦芒5 4g信号差怎么办 华为麦芒手机锁屏密码忘了怎么办 华为麦芒5相机拍相片倒了怎么办 红米5a开不了机怎么办 华为沾了海水打不开机怎么办 华为麦芒手机忘记锁屏密码怎么办 华为手机的方框键摁不了怎么办 笔记本自动更新到一半太慢了怎么办 华为麦芒5音量下键乱跑了怎么办 麦芒6手机QQ视频没声音怎么办 18:9看16:9黑边怎么办 华为畅享7s声音小怎么办 华为畅享8手机声音小怎么办 华为畅享8plus声音小怎么办 荣耀7x锁屏密码忘记怎么办 华为荣耀7x锁屏密码忘记了怎么办 苹果耳机进水后声音变了怎么办 华为荣耀开了数据用不了怎么办 华为手机高德地图信号弱怎么办? 手机QQ浏览器看视频有广告怎么办 手机显示网络连接但不可上网怎么办 华为手机关机后开不了机怎么办 华为畅享8p相机拍照模糊怎么办 手机触屏不准怎么办荣耀青春版九 华为手机锁屏手势密码忘了怎么办 荣耀手机锁屏密码忘了怎么办 华为p20隐私空间密码忘了怎么办 安全管家隐私保护的密码忘了怎么办 华为手机自带截图键删除了怎么办 飞科电吹风吹一会就断电怎么办 住酒店时电吹风吹坏了怎么办 把话费充到停机的号码上去了怎么办 电信手机卡充值了还停机怎么办 电信手机一直没用却欠费了怎么办 苹果se开起4g信号不好怎么办 触屏华为手机充不了电怎么办 华为手机自拍出来的字反向怎么办 华为微信隐藏了怎么弄出来怎么办 酷派手机酷管家密码忘了怎么办