工厂模式(AbstractFactory)-创建型模式
重要声明:
故事纯属虚构,如有雷同请勿对号入座,故事只是为了抛砖引玉,虽以第一人称和作者本人网名起但不代表本人真实想法,请勿把故事中人物和作者本人联系起来,故事本意只为模式创造前提条件
角色:
ü Wensi 主演WenSi
ü 女朋友 helen
ü 电瓶车服务员 waiter
剧情:
开场白:我的女朋友对我可真体贴啊,上次是饿着我,发现会把我饿坏了,这不,又想了个招控制我的开支,还能间接的减肥。大家来品品吧
Wensi :今天陪我去充公交卡吧
Helen :啊!又要冲卡了啊,前些天才充的怎么这么快就用完了
Wensi :是啊!每天做地铁一天就4块钱2人就8块钱一个月就是200多啊
Helen:那么多啊
Wensi :恩是啊
Helen :要不我们去买个电瓶车吧!以后你就背着我上班嘿嘿
Wensi :啊?
Helen :好不好嘛
Wensi :好..好..啊
旁白:我的娘啊,这回要苦死我了
Helen :那好我们就去看看吧,大路鸽,吉安特,金陵都不错啊
Wensi :恩好的啊
旁白:来到了电瓶车大卖场………………………………………………
电瓶车服务员:2位喜欢哪款车哈我们这里车都很好的,请随便看看
Helen :好的
Wensi :这个大路鸽?
电瓶车服务员:这款大路鸽最大马力<chmetcnv w:st="on" unitname="公里" sourcevalue="42" hasspace="False" negative="False" numbertype="1" tcsc="0"><span lang="EN-US">42</span>公里</chmetcnv>,一次加档 加4马力
Wensi:那,那个吉安特呢?
电瓶车服务员:这款吉安特最大马力<chmetcnv w:st="on" unitname="公里" sourcevalue="55" hasspace="False" negative="False" numbertype="1" tcsc="0"><span lang="EN-US">55</span>公里</chmetcnv>,一次加档 加5马力
Wensi:那,那个金陵呢
电瓶车服务员:这款金陵最大马力<chmetcnv w:st="on" unitname="公里" sourcevalue="62" hasspace="False" negative="False" numbertype="1" tcsc="0"><span lang="EN-US">62</span>公里</chmetcnv>,一次加档 加6马力
Wensi:我看吉安特比较适中,Helen你看呢
Helen :恩!那就试试车吧
电瓶车服务员:好的
旁白:我们试试车还不错。。。。
Wensi:好了就要它了,多少钱
电瓶车服务员:2200
旁白:汗!老贵啊。。。。。
Wensi:便宜点吧
电瓶车服务员:2100不能再便宜了哈
Wensi:好
旁白:背着女朋友一路汽车回了家那个乐哈。。。。
这个故事和我们今天要讲的模式有联系吗?当然有啦,我们来看看作为电动车大卖场有很多柜台有专门卖各种各样牌子的电瓶车,我们要在那么多的品牌电瓶车里挑选我们想要的电瓶车,那么我们就需要一个一个的试骑,直到自己挑选到一个满意的为止,我们发现电瓶车的操作是非常简单的,打开电瓶发动机,加油门,关闭发动机,所以的电瓶车的操作都是这样的那么这样的话对系统来说他们的操作接口是固定的,只是电瓶车的种类和各类电瓶车的系数在变,试车时电瓶车这个类在剧烈的变化着,这时他就符合工厂模式的条件了,那我们怎么用面向对象的设计模式来描述这个故事呢?
让我们来看看我如何用OOD来描述
<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><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:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 381.75pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CFANWEI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape>
大家可以看到我在电动车大卖场这里用了抽象工厂模式,让具体的电动车类延迟到子类实现,我们也能发现工厂模式经常是和抽象工厂一起合作完成一件事情当然也有很多时候是跟单件模式一起混合运用。
判定这个OOD设计是否合理我们依据我们第二章的设计模式原则来判定
1. 是否符合开闭原则
电动车大卖场在新添一种电瓶车和客户去试骑是我们只需要增加一个电瓶车的子类和大卖场的专柜,所以符合开闭原则
答案:符合
2. 是否符合里氏代换原则
不用不讲一下就明白
答案:符合
3. 是否符合合成复用原则
电瓶车的固有属性属于组合形式
答案:符合
4. 是否符合依赖倒置原则
我们在上图中不难发现人和电动车大卖场都是依赖与电动车这个抽象类的所以符合
答案:符合
5. 是否符合接口隔离原则
本模式中的接口只涉及到电动车的基本操作没有涉及其他任何不相干的操作所以符合
答案:符合
6. 是否符合抽象原则
答案:符合
7. 是否符合迪米特法则
大路鸽专卖店专门卖大路鸽,吉安特专卖店专门卖吉安特,金陵专卖店专门卖金陵。所以符合
答案:符合
总的来讲这个OOD设计是符合设计模式的要求
总结 :单件模式
意图:
提供一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类
动机:
软件系统中我们经常面临着一个类的形式剧烈变化着,但他的操作接口去不变时我们选择用工程模式
实用性:
l 当一个类不知道它所必须创建的对象的类的时候
l 当一个类希望由它的子类来指定它所创建的对象的时候
l 当类江创建对象的职责委托给多个帮助子类中的某一个,并你希望将哪一个帮助子类是代理者这一信息局部化的时候
结构:
<shape id="_x0000_i1026" style="WIDTH: 414.75pt; HEIGHT: 381.75pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CFANWEI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"><font size="3"></font></imagedata></shape>
参与者:
l AbstractFactory (生产工厂)
l ConcreteFactory (大路鸽专柜、吉安特专柜、金陵专柜)
l AbstractProduct (电瓶车)
l ConcreteProduct (大路鸽电瓶车、吉安特电瓶车、金陵电瓶车)
l Client (Helen 、Weisi、电瓶车服务员)
效果:
1. 为子类提供挂钩
2. 连接平行的类层次
代码: