您的位置:首页 > 其它

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

2012-10-01 22:13 543 查看
个人而言我认为工厂模式是应用最为广泛的一种模式了,工厂模式也属于创建型模式,一般来说分为:简单工厂模式、抽象工厂(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
}

// 默认外形1
return 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模式正如我在相应的文档中分析的是为一类对象提供创建接口。可以说AbstractFactory是Factory的一种拓展特例吧。

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

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

代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: