设计模式面面观(5):抽象工厂模式(AbstractFactory)-创建型模式

抽象工厂模式(AbstractFactory-创建型模式

重要声明:

故事纯属虚构,如有雷同请勿对号入座,故事只是为了抛砖引玉,虽以第一人称和作者本人网名起但不代表本人真实想法,请勿把故事中人物和作者本人联系起来,故事本意只为模式创造前提条件

角色:

ü Wensi 主演WenSi

ü 女朋友 helen

ü 肯德基服务员 kdj

ü 麦当劳服务员 mdl

剧情:

开场白:话说前回做个白日梦,过了一把皇帝瘾。回到现实来,好好找个女友谈谈,不谈不知道一谈下一跳啊,各位来品品我这个女友吧!人特好!?为了让我减肥让我跑东跑西还不控制我的食量…………

Wensi :今天吃什么

Helen :薯条,汉堡包

Wensi :那我们去肯德基还是麦当劳

Helen:不!

Wensi :那?

Helen :我要肯德基的薯条,麦当劳的汉堡

旁白:晕!这就是女人………………………………………………

WensiOK,那我们走吧

Helen:不! 你去买我在这里等你

旁白:汗!我怎么探上这样个女朋友啊………………………………

Wensi:好吧

旁白:来到肯德基。。。。

肯德基服务员:先生需要点什么?

Wensi:给我包薯条

肯德基服务员:薯条一包是吗,还需要点什么?我们这里新出来的3层汉堡味道不错,需要品尝一下吗?

Wensi:是的一包,其他不需要了

肯德基服务员:好的4.5

Wensi:给你5

肯德基服务员:OK!找您0.5元!请稍等………

肯德基服务员:给您价值4.5元的肯德基薯条!欢迎下次光临

旁白:离开肯德基,来到了麦当劳。。。。

麦当劳服务员:先生需要点什么?

Wensi:给我一个汉堡

麦当劳服务员:汉堡一个是吗,还需要点什么?我们这里新出来的鸡翅味道不错,需要品尝一下吗?

旁白:汗!天下乌鸦一般黑。。。。

Wensi:是的一包,其他不需要了

麦当劳服务员:好的11.5

Wensi:给你15

麦当劳服务员:OK!找您3.5元!请稍等………

麦当劳服务员:给您价值11.5元的麦当劳汉堡!欢迎下次光临

旁白:一路狂奔回来。。。。

Wensi:买回来了,一份薯条,一个汉堡

旁白:结果女朋友吧汉堡和薯条全吃了一个都没留给我!苦啊。。。。。。

这个故事和我们今天要讲的模式有联系吗?当然有啦,大家来看看故事的整个内容不难发现Wensi跑东跑西的为了只是那一份薯条一个汉堡,那么这些薯条和汉堡同属与肯德基和麦当劳主打叫卖的系列产品中的一员。Helen需要一份肯德基的薯条和麦当劳的一个汉堡包。Wensi去买这两样食品。这时肯德基和麦当劳好比一个食品加工厂(薯条、汉堡买来就是为了吃嘛所以这些就是食物而已),他们同时都生产薯条和汉堡包,但Helen要的却是其中之一的食物,那我们怎么用面向对象的设计模式来描述这个故事呢?

让我们来看看我如何用OOD来描述

设计模式面面观(5):抽象工厂模式(AbstractFactory)-创建型模式

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1026" style="WIDTH: 414.75pt; HEIGHT: 233.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz" o:title=""></imagedata></shape>

解释下为什么要这样做,用OOD的思想我们先从故事中可以知道一共用了几个角色,上面我已经罗列出来了,因为这里我并没有把人物对象的UML体现出来是因为这个在本章设计模式中并不重要,这里体现出来的是抽象工厂的结构图。抽现工厂的要义就是处理一系列的对象,那让我们看看把故事里的内容抽现出来的后抽象结构如下

设计模式面面观(5):抽象工厂模式(AbstractFactory)-创建型模式

<group id="_x0000_s1026" style="WIDTH: 414pt; HEIGHT: 241.8pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line" coordsize="7200,4212" editas="canvas" coordorigin="2362,8598"><lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_s1027" style="LEFT: 2362px; WIDTH: 7200px; POSITION: absolute; TOP: 8598px; HEIGHT: 4212px" o:preferrelative="f" type="#_x0000_t75"><font size="3"><fill o:detectmouseclick="t"></fill><path o:extrusionok="t" o:connecttype="none"></path><lock v:ext="edit" text="t"></lock></font></shape><oval id="_x0000_s1028" style="LEFT: 3771px; WIDTH: 2191px; POSITION: absolute; TOP: 9685px; HEIGHT: 815px"><font size="3"></font></oval><oval id="_x0000_s1029" style="LEFT: 3927px; WIDTH: 626px; POSITION: absolute; TOP: 9549px; HEIGHT: 2174px"><font size="3"></font></oval><line id="_x0000_s1030" style="POSITION: absolute; flip: y" to="3458,11995" from="3458,9277"><stroke endarrow="block"><font size="3"></font></stroke></line><line id="_x0000_s1031" style="POSITION: absolute" to="8936,11996" from="3458,11995"><stroke endarrow="block"><font size="3"></font></stroke></line><shapetype id="_x0000_t10" coordsize="21600,21600" o:spt="10" path="m@0,l0@0,0@2@0,21600@1,21600,21600@2,21600@0@1,xe" adj="6326"><stroke joinstyle="miter"></stroke><formulas><f eqn="val #0"></f><f eqn="sum width 0 #0"></f><f eqn="sum height 0 #0"></f><f eqn="prod @0 2929 10000"></f><f eqn="sum width 0 @3"></f><f eqn="sum height 0 @3"></f><f eqn="val width"></f><f eqn="val height"></f><f eqn="prod width 1 2"></f><f eqn="prod height 1 2"></f></formulas><path gradientshapeok="t" o:connecttype="custom" limo="10800,10800" o:connectlocs="@8,0;0,@9;@8,@7;@6,@9" textboxrect="0,0,21600,21600;2700,2700,18900,18900;5400,5400,16200,16200"></path><handles><h position="#0,topLeft" switch="" xrange="0,10800"></h></handles></shapetype><shape id="_x0000_s1032" style="LEFT: 4084px; WIDTH: 313px; POSITION: absolute; TOP: 9957px; HEIGHT: 271px" type="#_x0000_t10"><font size="3"></font></shape><shapetype id="_x0000_t5" coordsize="21600,21600" o:spt="5" path="m@0,l,21600r21600,xe" adj="10800"><stroke joinstyle="miter"></stroke><formulas><f eqn="val #0"></f><f eqn="prod #0 1 2"></f><f eqn="sum @1 10800 0"></f></formulas><path gradientshapeok="t" o:connecttype="custom" o:connectlocs="@0,0;@1,10800;0,21600;10800,21600;21600,21600;@2,10800" textboxrect="0,10800,10800,18000;5400,10800,16200,18000;10800,10800,21600,18000;0,7200,7200,21600;7200,7200,14400,21600;14400,7200,21600,21600"></path><handles><h position="#0,topLeft" xrange="0,21600"></h></handles></shapetype><shape id="_x0000_s1033" style="LEFT: 5179px; WIDTH: 313px; POSITION: absolute; TOP: 9957px; HEIGHT: 271px" type="#_x0000_t5"><font size="3"></font></shape><shape id="_x0000_s1034" style="LEFT: 4084px; WIDTH: 313px; POSITION: absolute; TOP: 11180px; HEIGHT: 271px" type="#_x0000_t10"><font size="3"></font></shape><shape id="_x0000_s1035" style="LEFT: 5179px; WIDTH: 313px; POSITION: absolute; TOP: 11180px; HEIGHT: 270px" type="#_x0000_t5"><font size="3"></font></shape><shape id="_x0000_s1036" style="LEFT: 4553px; WIDTH: 312px; POSITION: absolute; TOP: 12267px; HEIGHT: 270px" type="#_x0000_t10"><font size="3"></font></shape><line id="_x0000_s1037" style="POSITION: absolute" to="5179,12403" from="4866,12402"><font size="3"></font></line><rect id="_x0000_s1038" style="LEFT: 5179px; WIDTH: 783px; POSITION: absolute; TOP: 12267px; HEIGHT: 406px" strokeweight=".25pt"><stroke dashstyle="1 1" endcap="round"></stroke><textbox><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #e0dfe3; BORDER-BOTTOM-COLOR: #e0dfe3; BORDER-TOP-COLOR: #e0dfe3; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #e0dfe3"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><font size="3">薯条</font></span></p> </div> </td> </tr></tbody></table></textbox></rect><shape id="_x0000_s1039" style="LEFT: 6901px; WIDTH: 313px; POSITION: absolute; TOP: 12267px; HEIGHT: 270px" type="#_x0000_t5"><font size="3"></font></shape><line id="_x0000_s1040" style="POSITION: absolute" to="7685,12539" from="7214,12538"><font size="3"></font></line><rect id="_x0000_s1041" style="LEFT: 7684px; WIDTH: 781px; POSITION: absolute; TOP: 12267px; HEIGHT: 406px"><stroke dashstyle="1 1" endcap="round"></stroke><textbox><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #e0dfe3; BORDER-BOTTOM-COLOR: #e0dfe3; BORDER-TOP-COLOR: #e0dfe3; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #e0dfe3"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><font size="3">汉堡</font></span></p> </div> </td> </tr></tbody></table></textbox></rect><line id="_x0000_s1042" style="POSITION: absolute; flip: y" to="7371,10094" from="5962,10093"><stroke endarrow="block"><font size="3"></font></stroke></line><rect id="_x0000_s1043" style="LEFT: 7371px; WIDTH: 1408px; POSITION: absolute; TOP: 9821px; HEIGHT: 407px" strokeweight=".25pt" alt="系列产品"><stroke dashstyle="1 1" endcap="round"></stroke><textbox><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #e0dfe3; BORDER-BOTTOM-COLOR: #e0dfe3; BORDER-TOP-COLOR: #e0dfe3; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #e0dfe3"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><font size="3">系列产品</font></span></p> </div> </td> </tr></tbody></table></textbox></rect><line id="_x0000_s1044" style="POSITION: absolute; flip: y" to="7371,11045" from="4553,11044"></line><rect id="_x0000_s1045" style="LEFT: 7371px; WIDTH: 1408px; POSITION: absolute; TOP: 10772px; HEIGHT: 408px" strokeweight=".25pt" alt="系列产品"><stroke dashstyle="1 1" endcap="round"></stroke><textbox><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-LEFT-COLOR: #e0dfe3; BORDER-BOTTOM-COLOR: #e0dfe3; BORDER-TOP-COLOR: #e0dfe3; BACKGROUND-COLOR: transparent; BORDER-RIGHT-COLOR: #e0dfe3"> <div> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><font size="3">同类产品</font></span></p> </div> </td> </tr></tbody></table></textbox></rect><wrap type="none"></wrap><anchorlock></anchorlock></group>肯德基、麦当劳都是食品加工厂所以他们都继承与生产工厂这个抽象类,抽象工厂只负责生产食物(生产薯条,汉堡),而薯条,汉堡都是食品他们有共同的特性名字价格和生产厂商

判定这个OOD设计是否合理我们依据我们第二章的设计模式原则来判定

1. 是否符合开闭原则

抽象工厂模式是一个特定条件环境时支持开闭原则的模式,其他条件环境不支持。在扩展产品系列的时候是完美的支持开闭原则,在这里我们创建了肯德基工厂类和麦当劳工厂类,如果我们国内也有一个店(虚拟的)他也生产薯条和汉堡包,那么我们在扩展这个新的加工工厂时很轻松的就可以做到。反过来,如果中国政府突然颁发法令不允许中国国内生产薯条,只给生产薯片时大家发现虚拟的生产工厂就需要修改他的生产方法,而具体的生产工厂,肯德基、麦当劳也相应的也要同步修改(汗!这个工作量的大的要命了)所以在修改系列产品内部对象时抽象工厂就不是一个很好的支持开闭原则的设计模式了。所以抽象工厂是一种特定环境下的设计模式

答案:在特定环境中支持

2. 是否符合里氏代换原则

这里如果不用抽象工厂创建换成肯德基或麦当劳工厂自己生产是完全可以的所以符合

答案:符合

3. 是否符合合成复用原则

不模式不涉及到这个方面

答案:不涉及

4. 是否符合依赖倒置原则

Helen从抽象的生产工厂中获得她想要的食物。所以Helen依赖与这个抽象的生产工厂。抽象的生产工厂生产的出来的各种食品都是食物,所以抽象生产工厂依赖与抽象的食物类。他们都是依赖与抽象所以符合

答案:符合

5. 是否符合接口隔离原则

本模式没有涉及到接口

答案:不涉及

6. 是否符合抽象原则

答案:符合

7. 是否符合迪米特法则

肯德基、麦当劳兢兢业业的生产着他们的薯条和汉堡其他的任何事情都不干也不涉及。

答案:符合

总的来讲这个OOD设计是符合设计模式的要求

总结 :抽象工厂模式

意图

提供一个创建一系列相关或相互依赖对象的接口。而无需指定他们的具体的类

动机

软件系统中我们经常面临着一系列相关或相互依赖的对象的创建工作;同时由于需求的变化往往存在更多系列对象的创建工作。如何绕过常规的对象创建方法(new)提供一种封装机制来避免客户程序和这种多系列具体对象创建工作的紧耦合

实用性

l 一个系统要独立于他的产品的创建、组合和表示时(即客户不关心产品的生产过程只关心产品的使用是否合适)

l 一个系统要求多个产品系列中的一个来配置时(这个不难理解试想下Helen的要求就可以理解了)。

l 当你要强调一系列相关的产品对象的设计以便进行联合使用时

l 当你提供一个产品类库,只想显示他们的接口而不是现实时(这个在软件开发中相当重要,尽量减少软件对外的接口可以更好的保护软件的安全性)

结构

设计模式面面观(5):抽象工厂模式(AbstractFactory)-创建型模式

<shape id="_x0000_i1027" style="WIDTH: 327.75pt; HEIGHT: 353.25pt" type="#_x0000_t75" alt=""><imagedata src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image004.gif" o:href="http://www.cnblogs.com/images/cnblogs_com/zhenyulu/Pic46.gif"><font size="3"></font></imagedata></shape>

参与者

l AbstractFactory (生产工厂)

l ConcreteFactory (肯德基、麦当劳)

l AbstractProduct (食物)

l ConcreteProduct (薯条、汉堡)

l Client (Helen )

效果

1. 分离具体的类和创建对象:生产工厂帮我们控制到底需要创建哪个具体的食品加工厂

2. 定义了一个可扩展的工厂(只能横向扩展不能纵向扩展)

代码

http://download.csdn.net/source/257946

<stroke endarrow="block"><font size="3"></font></stroke>

<stroke endarrow="block"></stroke>

你可能感兴趣的:(设计模式,F#,ext,UML)