您的位置:首页 > 其它

设计模式之工厂模式二三事

2013-05-15 00:25 141 查看
很久没有写过C++的项目了,最近看了看设计模式,对于工厂模式略有心得,故写出来分享。

工厂模式大致分为三类:简单工厂模式、工厂方法模式、抽象工厂模式

OK,上图说明,还是用网上流行的做菜比喻。

无工厂情况



我想吃红烧鱼,没问题,我自己做(new):

Fish *f = new BraisingFish; //自己做红烧鱼

f->Delicious(); //美味啊

可是做了几天后,我不想自己做(new)了,太累,咋办?建一个烹饪鱼工厂给我做鱼。

简单工厂模式



我想吃红烧鱼,现在不用自己做(new)了,直接去找烹饪工厂,烹饪工厂给我做红烧鱼(CookFish)

CookFishFactory *cff = new CookFishFactory; //烹饪工厂

Fish *f = cff->CookFish(); //烹饪工厂给我做红烧鱼

f->Delicious(); //美味啊

优点:1、以后都不用自己做红烧鱼了,直接让工厂做。(解决了代码中大量New的问题)。

           2、工厂做鱼的方式更灵活,我什么都不用管了。

缺点:下面就说。

工厂方法模式

天天都吃红烧鱼,扛不住了,我要吃清蒸鱼,怎么办?自己做?太累了,还得学清蒸鱼的做法,改进烹饪工厂?不行,不能改进工厂(开闭法则),怎么办?!无解啊,看来简单工厂模式不行,我得换一种模式,不能由烹饪鱼工厂来直接做红烧鱼, 我专门建一个烹饪红烧鱼的工厂,让烹饪鱼工厂将烹饪红烧鱼的工作外包给烹饪红烧鱼的工厂。



我想吃红烧鱼,先找烹饪鱼工厂,烹饪鱼工厂将工作外包给烹饪红烧鱼的工厂:

CookFishFactory *cff = new CookBraisingFishFactory;

Fish *f = cff->CookFish();

f->Delicious();

那么我想吃清蒸鱼咋办?!

增加一个清蒸鱼的外包工厂



这样当我想吃清蒸鱼了,

CookFishFactory *cf = new CookSteamedFactory;

FoodProduct *fp = cf->CookFood();

这样,在不违背开闭法则的前提下解决了简单工厂模式的缺点。

优点:1、简单工厂模式具有的优点。

           2、解决了简单工厂模式的缺点。

缺点:下面说。

抽象工厂模式

天天吃鱼,不行,腻了,想换换口味,吃点猪肉吧,怎么办?在工厂方法模式下,我可以再建一个烹饪猪肉的工厂,然后下面有烹饪红烧肉啊,清蒸肉啊等等,这当然可以,但为了吃猪肉,我得建好几个工厂,譬如红烧肉工厂、清蒸肉工厂,有没有办法不建这么多工厂呢?!

怀着这个想法,我发现不管是鱼还是肉,都有几种相同的做法,譬如红烧,清蒸。



横坐标表示肉类,有鱼肉、猪肉(产品等级结构),纵坐标表示制作方法(产品族),可清蒸,可红烧,这样,我可以再次设计我的工厂,分为红烧工厂和清蒸工厂,一个工厂可以做两种肉类(抽象工厂)。





如果我想吃红烧肉,我可以这样做:

CookFactory *cf = new CookBraisingFactory;

Pork *p = cf->CookPork();

p->Delicious();

如果我想吃清蒸肉,这样做:

CookFactory *cf = new CookSteamedFactory;

Pork *p = cf->CookPork();

p->Delicious();

红烧鱼做法:

CookFactory *cf = new CookBraisingFactory;

Fish *f = cf->CookFish();

f->Delicious();

清蒸鱼做法:

CookFactory *cf = new CookSteamedFactory;

Fish *f = cf->CookFish();

f->Delicious();

这样,如果我又想出一种新的做法,譬如水煮的时候,我可以新建一个水煮的工厂,同时做水煮鱼和水煮肉。



但是,如果我想增加一种肉类,比如鸡肉咋办?!没辙。

那么抽象工厂模式有什么优点呢?因为我吃的肉类是有限的,就鸡肉、鱼肉、猪肉、牛肉等等,轻易不会再增加肉的类型了,但各种肉的制作方法是有不同的,而且可以增加,比如油闷,爆炒等等,什么时候我想出了一种新做法,直接增加一个相应的工厂就行,不用再根据不同的原料与不同的做法增加不同的工厂。

OK,不说吃了,拿IT举个例子吧,譬如QT图形库,图形库由很多组件组成,有button,view,widget等等,这些东西就相当于我们的猪肉、鱼肉、牛肉等等,QT是跨平台的,可以在windows上跑,可以在linux上跑,也可以在OSX上跑,这些平台,就相当于我们的红烧工厂、清蒸工厂、水煮工厂。如果我们需要增加一个产品族,譬如在Solaris上跑的话,很容易,增加一个工厂就行,不会违背开闭法则,但如果想增加一个产品等级结构,譬如增加一个控件,就很麻烦了,需要修改所有的工厂,会违背开闭法则。

优点:很容易增加产品族,不违背开闭法则。

缺点:难以添加产品等级结构,会违背开闭法则。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: