设计模式(2) –工厂模式(Factory)

来源:互联网 发布:数据库int设置取值范围 编辑:程序博客网 时间:2024/06/15 17:27

       个人而言我认为工厂模式是应用最为广泛的一种模式了,工厂模式也属于创建型模式,一般来说分为:简单工厂模式、抽象工厂(AbstactFactory)模式。这个模式有什么好处呢?我们可以通过下面这个例子来探讨:
        假设工厂生产一些了很多种产品,并且需要为这些产品设计很多的包装,每个产品用来展示用各自的包装设计展示给客户看。于是几年前的我可能就会写出如下的代码:      

class CProductAShow {public:void AShow(){cout<<"产品A的外观"<<endl;}// ...其他的展示外观};class CProductA{public:void ShowA(){m_show.AShow();}private:CProductAShow m_show;};

     上面的代码看是没啥问题,但在实际工作中我们会遇到这样问题:

今天产品A换了新的包装,那么我们就必须得把A 代码进行修改,同时新增一个新的外形设计类或者直接修改旧的设计类CProductAShow代码,或者我们同一个产品面对不同的地区希望生产不同的外观的产品,那么这时候我们又要怎么去修改呢?

        针对上面的问题,我们可能就要和设计师交流,告诉设计师我们需要一个怎样的产品,,从代码角度上说我们就需要考虑一个比较通用的接口来实现代码了,尽量使代码减少耦合,这个时候我们可以进行这样的修改:     

代码01:

//构造一个外观设计基类class CShowBase{public:virtual void Show()=0;virtual ~CShowBase(){cout<<"释放基类自己的内容"<<endl;}};class CProductAShowNG1:public  CShowBase{public:void Show(){cout<<"NG1 产品A的外观"<<endl;}~CProductAShowNG1(){cout<<"释放 NG1 产品A的外观"<<endl;}static void Release( CShowBase *p ){delete (CProductAShowNG1*)p;}// ...其他的展示外观};class CProductAShowNG2:public  CShowBase{public:void Show(){cout<<"NG2 产品A的外观"<<endl;}~CProductAShowNG2(){cout<<"释放 NG2 产品A的外观"<<endl;}static void Release(CShowBase *p){delete (CProductAShowNG2*)p;}// ...其他的展示外观};typedef void (*Release) (CShowBase *) ;   // 释放外形设计的指针// 引进外形设计师来了,这个其实就是一个工厂,因为只要你告诉他们需求类型,他们就会生产了各种各样的外观设计class CDesigner    {    public:     static CShowBase* CreateShowed(int nType ,Release *prel)    {    if(nType == 1) //外形1{if (prel != NULL) *prel = CProductAShowNG1::Release;return new CProductAShowNG1(); //外形1}else if(nType == 2)    {if (prel != NULL) *prel = CProductAShowNG2::Release; // 资源释放指针return new CProductAShowNG2(); //外形2}// 默认外形1return new CProductAShowNG1(); }    };    class CProductANG1{public:CProductANG1(int type){m_pshow=NULL;m_pshow=CDesigner::CreateShowed(type,&m_ReleaseShow);}~CProductANG1(){if (m_pshow){m_ReleaseShow(m_pshow);}}void ShowA(){m_pshow->Show();}private:CShowBase *m_pshow;Release m_ReleaseShow;//};int _tmain(int argc, _TCHAR* argv[]){CProductA oPA;oPA.ShowA();{CProductANG1 oPNGA(1);oPNGA.ShowA();}CProductANG1 oPNGA2(2);oPNGA2.ShowA();getchar();return 0;}

输出:



        可以看出要通过上面的方法,我们引进了外观设计者这个人(其实他就是一个产生外观对象的工厂)--工厂模式在这里体现出现了!!我们只需要告诉设计师我们需要什么类型的产品外观,他就会给我们返回一个通用接口的外观设计了,这样可以比较简单的实现了自己的产品的新外观需求了,基本上我们不需要更改ProductANG1们的代码,只需要新增设计者的类型就可以了。这边有一个需要注意的一点是关于继承类的释放,通常是一个比较容易犯错误的地方,容易引起一些内存未释放,这里我采用的是对函数指针的赋值,使其指向对应的释放函数就可以避免这样的问题产生了。                                                                                                                                                                                                                                                                     

        事情发展到了这步好像可以达到我们的需求了,这个时候工厂又来了一个设计师,他设计的产品相对原来的设计师各有特色,于是客户有的指定设计师A 设计他们的产品外观,有的则希望用新来的设计师B 来设计他们要的产品。这样麻烦有来了,我们又需要去修改ProductANG1的代码了 ,悲剧啊抓狂,为神马程序猿要面对这么多样的需求呢?

        为了一次解决这类问题,我们需要一个更大的boss(总设计师)来让设计师们去做对应的事情了,为了减少代码的耦合性,我们再次将外观分开为每个设计师独有的形式,我们称这个boss为抽象工厂。

        

代码如下:

// 新的外观显示类

ShowBaseNG2.h:

/* 版权说明: 本代码版权 为 糙级码lee 所有 转载请注明来自:http://blog.csdn.net/zerolxl  */  #ifndef __SHOW_TYPE_H__#define __SHOW_TYPE_H__class CShowBaseNG2{public:virtual void Show()=0;virtual ~CShowBaseNG2(){};};class CProductShowByDesA: public CShowBaseNG2{public:void Show();virtual ~CProductShowByDesA();};class CProductShowByDesB: public CShowBaseNG2{public:virtual void Show();virtual ~CProductShowByDesB();};#endif //__SHOW_TYPE_H__
ShowBaseNG2.cpp:

#include "stdafx.h"#include "ShowBaseNG2.h"#include "string"#include "iostream"using namespace std;void CProductShowByDesA::Show(){cout<<"设计师A 设计出产品 "<<endl;}CProductShowByDesA::~CProductShowByDesA(){cout<<"释放CProductShowByDesA基类自己的内容"<<endl;}void CProductShowByDesB::Show(){cout<<"设计师B 设计出产品 "<<endl;}CProductShowByDesB::~CProductShowByDesB(){cout<<"释放CProductShowByDesB基类自己的内容"<<endl;}

// 设计师们

Designer.h

/*版权说明: 本代码版权 为 糙级码lee 所有转载请注明来自:http://blog.csdn.net/zerolxl  */  #ifndef __FACTORY_TYPE_H__#define __FACTORY_TYPE_H__class CShowBaseNG2;// 是设计师的基类  可看做总设计师  class CAbstractDesignerBase{public:    virtual ~CAbstractDesignerBase();    virtual CShowBaseNG2* CreateShow() = 0;    CAbstractDesignerBase(){};};// 设计师A 的作品class CDesignerA:public CAbstractDesignerBase{public:    ~CDesignerA();    CDesignerA();    CShowBaseNG2* CreateShow();};// 设计师B 的作品class CDesignerB:public CAbstractDesignerBase{public:    ~CDesignerB();    CDesignerB();    CShowBaseNG2* CreateShow();};#endif //__FACTORY_TYPE_H__
Designer.cpp:

#include "stdafx.h"#include "Designer.h"#include "ShowBaseNG2.h"#include "string"#include "iostream"using namespace std;CAbstractDesignerBase::~CAbstractDesignerBase() {cout<<"释放总设计师开辟的空间"<<endl;}CDesignerA::~CDesignerA(){cout<<"释放设计师A 开辟的空间"<<endl;}CDesignerA::CDesignerA(){}CShowBaseNG2* CDesignerA::CreateShow(){return new CProductShowByDesA();}CDesignerB::~CDesignerB(){cout<<"释放设计师B 开辟的空间"<<endl;}CDesignerB::CDesignerB(){}CShowBaseNG2* CDesignerB::CreateShow(){return new CProductShowByDesB();}
int _tmain(int argc, _TCHAR* argv[]){{CAbstractDesignerBase *pDesigner=new CDesignerA();CShowBaseNG2 *pShow=pDesigner->CreateShow();pShow->Show();delete pDesigner;}{CAbstractDesignerBase *pDesigner=new CDesignerB();CShowBaseNG2 *pShow=pDesigner->CreateShow();pShow->Show();delete pDesigner;}getchar();return 0;}
输出:

     

    通过总设计师的控制,我们可以比较清楚的将各个外观分配给产品显示,提高后期的维护效率,但是显然这样也增加了类的个数。

下面展示一下本片文章的类图示意图:

    第一个想法:

    

从图可以看出产品和外观是耦合在在一起的,具有一定的耦合性。

  普通工厂:

 

  可以看出这个时候产品已经和外观通过一个base来建立连接了。减少了代码的耦合性。


抽象工厂:

              


             我们可以看到:实际上,AbstractFactory模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式正如我在相应的文档中分析的是为一类对象提供创建接口。可以说AbstractFactoryFactory的一种拓展特例吧。


              凌晨一点半了,有点累了,睡觉啦了。说的不对之处,欢迎拍砖 ,明天起来上传本文源码。。

                                                                                                              转载请注明来自:http://blog.csdn.net/zerolxl     


代码下载


           

        



原创粉丝点击