C#设计模式之工厂
IronMan之工厂
前言
实用为主,学一些用得到的技术更能在如今的社会里保命。虽然在日常的工作中设计模式不是经常的用到,但是呢,学习它只有好处没有坏处。
设计模式像是一种“标签”,它是代码编写者思想的体现。有木有感觉到这样很便捷?看到一些代码的时候就很清楚的了解编写者的思想了,这是为什么呢?因为编写者们用了“标签”,而你恰恰是知道“标签”意思的。跟一异曲同工,在学习框架、了解框架的对象模型的时候,“标签”是时常出现,如果你不了解“标签”的意思那多痛苦啊!!!!!还有好多,不去一一阐述了。
工作中需求的变更时常令我们头疼不已,总是要按着需求来重新的修改代码,然后发布新的产品版本,或者是出更新包。在需求变更中,对应着代码也要修改,但是这修改也是分层次的。比如修改的模板在当初设计的时候遵循了开闭原则(OCP)的话,代码的修改就变的轻松的多了。
我想制造出一个像电影《钢铁侠》里面那样的的一身盔甲,又或者说是机器吧,我把这个想法告诉了我的朋友们,他们都认为我疯了。
好吧,我说的是用代码抽象的制造出”钢铁侠“
废话不多说,下面这个系列是用钢铁侠(IronMan)作为主题的设计模式今天来学习简单工厂模式、工厂方法模式、以及抽象工厂模式。
问题的发现
需求:
“玩具厂”有一天找到我说:“Jin叫兽我们这需要一些部件,我们会提供“图纸”,请您帮忙制造,您看有问题吗?”。
我:“当然没有问题了。很乐意帮助你们”。
“玩具厂”:“噢!好的。Jin叫兽,时间方面还有什么问题嘛?”
我:“没问题的,我会尽快的”。
“玩具厂”:“那真的太感谢您了,Jin叫兽。我们就不打扰您了,先走了。”
我:“晚上一起吃顿饭吧”。
“玩具厂”:“Jin叫兽不必客气啊”。
我:“好,你们慢走”。
生产车间:
“一点挑战性都没有,随随便便就制造出来了。先从组成‘钢铁侠’的部件开始生产吧。”
既然是这样,那就从部件开始生产吧。
这里是“玩具厂”提供的“钢铁侠”右臂的“图纸”:
1publicclassRightHandComponent2{3publicRightHandComponent()4{5this.strName="毅代先锋号一代右部件";67}8publicRightHandComponent(stringstrname)9{10this.strName=strname;11}12privatestringstrName=string.Empty;13publicstringName14{15get{returnstrName;}16set{strName=value;}17}18}
还有一个左臂部件的“图纸”:
1publicclassLeftHandComponent2{3publicLeftHandComponent()4{5this.strName="毅代先锋号一代左部件";6}7privatestringstrName=string.Empty;8publicstringName9{10get{returnstrName;}11set{strName=value;}12}13}
还有若干“图纸”……不在这篇一一列举了,在后面文章中会全面的讲解到。
开始生产
RightHandComponentrightcomponent=newRightHandComponent();LeftHandComponentleftcomponent=newLeftHandComponent();
若干的部件
被我一个个的按照图纸给制造了出来。
这样就可以拿rightcomponent、leftcomponent……等等的一些制造好的部件组装了。
我也可以给“玩具厂”打电话了,可以交货收钱。可是电话打完情况又变了,
中间的对话就不说了,“玩具厂”的意思就是这样的。比如说“运输途中”出现“损坏”,他们希望用一个很快捷便利的方式能得到部件。
简单工厂
嗯,我想了一下,不过对于我Jin叫兽来说都是小事,待我造出来一台部件生产器来。他们拿着机器自己回家生产不就ok了。
publicclassIronManComponentFactory{publicstaticobjectCreateComponent(stringcomname){switch(comname){case"RightCom":returnnewRightHandComponent();case"LeftCom":returnnewLeftHandComponent();等等……}returnnull;}}
这样生产的“机器”就好了,我得自己试用一下,看看效果怎么样。
1RightHandComponentrightcomponent=IronManComponentFactory.CreateComponent("RightCom")asRightHandComponent;2LeftHandComponentleftcomponent=IronManComponentFactory.CreateComponent("LeftCom")asLeftHandComponent;
这样反而多此一举了,第一步,向机器输入了命令以便自己获得想要的部件,第二步,在生产出来后我还得把“图纸”拿过来比对一下。在我一筹莫展的时候,“玩具厂”给我发了个邮件,给我发了一份“部件规范说明书”,要求我的机器生产出的部件是达到说明书标准的。
那我们就来看一下这个所谓的“部件规范说明书”
1publicabstractclassComponent2{3privatestringstrName=string.Empty;4///<summary>5///名称6///</summary>7publicstringName8{9get{returnstrName;}10set{strName=value;}11}12///<summary>13///自我描述14///</summary>15publicabstractvoidSelf_Described();16}
看完这个“部件规范说明书”,我已经无力吐槽,没办法了,只有重新设计部件了,“图纸”要重新绘制,因为要按照那该死的“规范说明书”。
再看一下各个部件的“图纸”
1publicclassRightHandComponent:Component2{3publicRightHandComponent()4{5base.Name="毅代先锋号一代右部件";6//fWeight=材质输出7}8publicRightHandComponent(stringstrname)9{10base.Name=strname;11}12publicoverridevoidSelf_Described()13{14Console.WriteLine(base.Name);15}16}17publicclassLeftHandComponent:Component18{19publicLeftHandComponent()20{21base.Name="毅代先锋号一代左部件";22}23publicLeftHandComponent(stringstrname)24{25base.Name=strname;26}27publicoverridevoidSelf_Described()28{29Console.WriteLine(base.Name);30}31}
等等一些部件……
这下我再把原来的搭好的“生产机器”拆了,内部修改一下,来看一下修改后的“机器”
1publicclassIronManComponentFactory2{3publicstaticComponentCreateComponent(stringcomname)4{5switch(comname)6{7case"RightCom":8returnnewRightHandComponent();9case"LeftCom":10returnnewLeftHandComponent();1112}13returnnull;14}15}
自己来测试一下:
1Componentrightcomponent=IronManComponentFactory.CreateComponent("RightCom");2Componentleftcomponent=IronManComponentFactory.CreateComponent("LeftCom");3rightcomponent.Self_Described();4leftcomponent.Self_Described();
于是,我很放心的就交给了“玩具厂”使用了,还得了个好评。
工厂方法
好景不长,“玩具厂”再次来电,提出一个要求,想让我的“生产机器”里面还可以生产更多的符合“部件规范说明书”的部件。
这样说来是要改装“生产机器”了。可以说“玩具厂”是故意的,绝对是故意的。这下整蒙圈了,亏血本了,“生产机器”又要拆了……直接来看“生产机器”的图纸
1publicabstractclassIronManComponentFactory2{3protectedstringfactoryName=string.Empty;4protectedvoidInitDataMessage()5{6Console.WriteLine("生产机器:"+factoryName+".准备就绪");7}8publicabstractComponentCreateComponent();9}10publicclassRightComFactory:IronManComponentFactory11{1213publicoverrideComponentCreateComponent()14{15base.factoryName="右臂部件生产器";16InitDataMessage();17returnnewRightHandComponent();18}19}20publicclassLeftComFactory:IronManComponentFactory21{2223publicoverrideComponentCreateComponent()24{25base.factoryName="左臂部件生产器";26InitDataMessage();27returnnewLeftHandComponent();28}29}30publicclassPottingFactrory31{32///<summary>33///取件口34///</summary>35///<paramname="comFactory"></param>36///<returns></returns>37publicstaticComponentComExit(IronManComponentFactorycomFactory)38{39if(comFactory!=null)40{41returncomFactory.CreateComponent();42}43returnnull;44}45}
我们通过“取件口”取件
1Componentcomponent=PottingFactrory.ComExit(newRightComFactory());2component.Self_Described();
我们只要通过更换“生产插件”,从“取件口”获得不同的部件。或者更改需求,又要生产符合“规范说明书”的另一些产品的时候,可以自定义来实现“生产插件”,插入“生产机器”即可。
这样可以送给“玩具厂”使用了。这次得到了很好的一个评价,我也可以休息一下了。
这里的工厂方法是开闭原则(OCP)的实现,很优雅的显示出了设计原则和设计模式的美。
抽象工厂
“对,没错。‘玩具厂’又来了……。”
这次“玩具厂”是把Iron部件升级了,二代部件出来了,是在一代的基础上做了一些个性化的设计。来看新增部件的“图纸”
1publicclassRightHandComponent2:Component2{3publicRightHandComponent2():this("毅代先锋号二代右部件"){}4publicRightHandComponent2(stringstrname)5{6base.Name=strname;7}8publicoverridevoidSelf_Described()9{10Console.WriteLine("自描述:我是->"+base.Name);11}12}1314publicclassLeftHandComponent2:Component15{16publicLeftHandComponent2():this("毅代先锋号一代左部件"){}17publicLeftHandComponent2(stringstrname)18{19base.Name=strname;20}21publicoverridevoidSelf_Described()22{23Console.WriteLine("自描述:我是->"+base.Name);24}25}
按照“规范说明书”,添加了两张“图纸”,它们分别是二代的左右手部件。
部件的整体结构没怎么变,但是“生产机器”的“规范说明”就要更改了,以为在上面说到的“生产插件”也要重新更改。
先来看一下“生产机器”的“规范说明”:
1publicabstractclassIronManComponentFactory2{3protectedstringfactoryName=string.Empty;4protectedvoidInitDataMessage()5{6Console.WriteLine("生产机器:"+factoryName+".准备就绪");7}8publicabstractComponentCreateComponent();9publicabstractComponentCreateComponent2();101112}
当然喽,“规范说明”都改了,那上面说过的两个生产插件也得改了:
1publicclassRightComFactory:IronManComponentFactory//右部件生产插件2{34publicoverrideComponentCreateComponent()5{6base.factoryName="新右臂部件生产器";7InitDataMessage();8returnnewRightHandComponent();9}1011publicoverrideComponentCreateComponent2()12{13base.factoryName="新右臂部件生产器";14InitDataMessage();15returnnewRightHandComponent2();16}17}1819publicclassLeftComFactory:IronManComponentFactory//左部件生产插件20{2122publicoverrideComponentCreateComponent()23{24base.factoryName="新左臂部件生产器";25InitDataMessage();26returnnewLeftHandComponent();27}2829publicoverrideComponentCreateComponent2()30{31base.factoryName="新左臂部件生产器";32InitDataMessage();33returnnewLeftHandComponent2();34}35}
所要做的修改都是连带关系,包装”生产机器“的”取件口“也要改:
1publicclassPottingFactory2{3privateIronManComponentFactorycomFactory=null;45publicIronManComponentFactoryComFactory6{7get{returncomFactory;}8set{comFactory=value;}9}10publicPottingFactory(IronManComponentFactorycomFactory)11{12this.comFactory=comFactory;13}14///<summary>15///取件口16///</summary>17///<paramname="comFactory"></param>18///<returns></returns>19//publicstaticComponentComExit(IronManComponentFactorycomFactory)20//{21//if(comFactory!=null)22//{23//returncomFactory.CreateComponent();24//}25//returnnull;26//}27}
到这里就差不多结束了。在工厂方法模式上做了稍稍的(几乎全改了)改动。
当然自己要先来测试一下喽:
1PottingFactorypottingfact=newPottingFactory(newRightComFactory());2Componentcomponent=pottingfact.ComFactory.CreateComponent();3component.Self_Described();4component=pottingfact.ComFactory.CreateComponent2();5component.Self_Described();
我们来看一下结果:
EndIronMan之旅才刚刚开始
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。