IronMan之工厂
前言
实用为主,学一些用得到的技术更能在如今的社会里保命。 虽然在日常的工作中设计模式不是经常的用到,但是呢,学习它只有好处没有坏处。
设计模式像是一种“标签”,它是代码编写者思想的体现。有木有感觉到这样很便捷?看到一些代码的时候就很清楚的了解编写者的思想了,这是为什么呢?因为编写者们用了“标签”,而你恰恰是知道“标签”意思的。 跟一异曲同工,在学习框架、了解框架的对象模型的时候,“标签”是时常出现,如果你不了解“标签”的意思那多痛苦啊!!!!! 还有好多,不去一一阐述了。
工作中需求的变更时常令我们头疼不已,总是要按着需求来重新的修改代码,然后发布新的产品版本,或者是出更新包。 在需求变更中,对应着代码也要修改,但是这修改也是分层次的。比如修改的模板在当初设计的时候遵循了开闭原则(OCP)的话,代码的修改就变的轻松的多了。
我想制造出一个像电影《钢铁侠》里面那样的的一身盔甲,又或者说是机器吧,我把这个想法告诉了我的朋友们,他们都认为我疯了。
好吧,我说的是用代码抽象的制造出”钢铁侠“
废话不多说,下面这个系列是用钢铁侠(IronMan)作为主题的设计模式 今天来学习简单工厂模式、工厂方法模式、以及抽象工厂模式。
问题的发现
需求:
“玩具厂”有一天找到我说:“Jin叫兽我们这需要一些部件,我们会提供“图纸”,请您帮忙制造,您看有问题吗?”。
我:“当然没有问题了。很乐意帮助你们”。
“玩具厂”:“噢!好的。Jin叫兽,时间方面还有什么问题嘛?”
我:“没问题的,我会尽快的”。
“玩具厂”:“那真的太感谢您了,Jin叫兽。我们就不打扰您了,先走了。”
我:“晚上一起吃顿饭吧”。
“玩具厂”:“Jin叫兽不必客气啊”。
我:“好,你们慢走”。
生产车间:
“一点挑战性都没有,随随便便就制造出来了。先从组成‘钢铁侠’的部件开始生产吧。”
既然是这样,那就从部件开始生产吧。
这里是“玩具厂”提供的“钢铁侠”右臂的“图纸”:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<code>1 </code><code>public</code> <code>class</code> <code>RightHandComponent</code>
<code>2 {</code>
<code>3 </code><code>public</code> <code>RightHandComponent()</code>
<code>4 {</code>
<code>5 </code><code>this</code><code>.strName = </code><code>"毅代先锋号一代右部件"</code><code>;</code>
<code>6</code>
<code>7 }</code>
<code>8 </code><code>public</code> <code>RightHandComponent(</code><code>string</code> <code>strname)</code>
<code>9 {</code>
<code>10 </code><code>this</code><code>.strName = strname;</code>
<code>11 }</code>
<code>12 </code><code>private</code> <code>string</code> <code>strName = </code><code>string</code><code>.Empty;</code>
<code>13 </code><code>public</code> <code>string</code> <code>Name</code>
<code>14 {</code>
<code>15 </code><code>get</code> <code>{ </code><code>return</code> <code>strName; }</code>
<code>16 </code><code>set</code> <code>{ strName = value; }</code>
<code>17 }</code>
<code>18 }</code>
还有一个左臂部件的“图纸”:
<code>1 </code><code>public</code> <code>class</code> <code>LeftHandComponent</code>
<code>3 </code><code>public</code> <code>LeftHandComponent()</code>
<code>5 </code><code>this</code><code>.strName = </code><code>"毅代先锋号一代左部件"</code><code>;</code>
<code>6 }</code>
<code>7 </code><code>private</code> <code>string</code> <code>strName = </code><code>string</code><code>.Empty;</code>
<code>8 </code><code>public</code> <code>string</code> <code>Name</code>
<code>10 </code><code>get</code> <code>{ </code><code>return</code> <code>strName; }</code>
<code>11 </code><code>set</code> <code>{ strName = value; }</code>
<code>12 }</code>
<code>13 }</code>
还有若干“图纸”…… 不在这篇一一列举了,在后面文章中会全面的讲解到。
开始生产
<code>RightHandComponent rightcomponent = </code><code>new</code> <code>RightHandComponent();</code>
<code>LeftHandComponent leftcomponent = </code><code>new</code> <code>LeftHandComponent();</code>
若干的部件
被我一个个的按照图纸给制造了出来。
这样就可以拿rightcomponent、leftcomponent……等等的一些制造好的部件组装了。
我也可以给“玩具厂”打电话了,可以交货收钱。可是电话打完情况又变了,
中间的对话就不说了,“玩具厂”的意思就是这样的。比如说“运输途中”出现“损坏”,他们希望用一个很快捷便利的方式能得到部件。
简单工厂
嗯,我想了一下,不过对于我Jin叫兽来说都是小事,待我造出来一台部件生产器来。他们拿着机器自己回家生产不就ok了。
<code>public</code> <code>class</code> <code>IronManComponentFactory</code>
<code>{</code>
<code>public</code> <code>static</code> <code>object</code> <code>CreateComponent(</code><code>string</code> <code>comname)</code>
<code>switch</code> <code>(comname)</code>
<code>case</code> <code>"RightCom"</code><code>:</code>
<code>return</code> <code>new</code> <code>RightHandComponent();</code>
<code>case</code> <code>"LeftCom"</code><code>:</code>
<code>return</code> <code>new</code> <code>LeftHandComponent();</code>
<code>等等……</code>
<code>}</code>
<code>return</code> <code>null</code><code>;</code>
这样生产的“机器”就好了,我得自己试用一下,看看效果怎么样。
<code>1 RightHandComponent rightcomponent = IronManComponentFactory.CreateComponent(</code><code>"RightCom"</code><code>) </code><code>as</code> <code>RightHandComponent;</code>
<code>2 LeftHandComponent leftcomponent = IronManComponentFactory.CreateComponent(</code><code>"LeftCom"</code><code>) </code><code>as</code> <code>LeftHandComponent;</code>
那我们就来看一下这个所谓的“部件规范说明书”
<code>1 </code><code>public</code> <code>abstract</code> <code>class</code> <code>Component</code>
<code>2 {</code>
<code>3 </code><code>private</code> <code>string</code> <code>strName = </code><code>string</code><code>.Empty;</code>
<code>4 </code><code>/// <summary></code>
<code>5 </code><code>/// 名称</code>
<code>6 </code><code>/// </summary></code>
<code>7 </code><code>public</code> <code>string</code> <code>Name</code>
<code>8 {</code>
<code>9 </code><code>get</code> <code>{ </code><code>return</code> <code>strName; }</code>
<code>10 </code><code>set</code> <code>{ strName = value; }</code>
<code>12 </code><code>/// <summary></code>
<code>13 </code><code>/// 自我描述</code>
<code>14 </code><code>/// </summary></code>
<code>15 </code><code>public</code> <code>abstract</code> <code>void</code> <code>Self_Described();</code>
<code>16 }</code>
看完这个“部件规范说明书”,我已经无力吐槽,没办法了,只有重新设计部件了,“图纸”要重新绘制,因为要按照那该死的“规范说明书”。
再看一下各个部件的“图纸”
19
20
21
22
23
24
25
26
27
28
29
30
31
<code>1 </code><code>public</code> <code>class</code> <code>RightHandComponent:Component</code>
<code>5 </code><code>base</code><code>.Name = </code><code>"毅代先锋号一代右部件"</code><code>;</code>
<code>6 </code><code>//fWeight=材质输出</code>
<code>10 </code><code>base</code><code>.Name = strname;</code>
<code>12 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>13 {</code>
<code>14 Console.WriteLine(</code><code>base</code><code>.Name);</code>
<code>15 }</code>
<code>17 </code><code>public</code> <code>class</code> <code>LeftHandComponent:Component</code>
<code>18 {</code>
<code>19 </code><code>public</code> <code>LeftHandComponent()</code>
<code>20 {</code>
<code>21 </code><code>base</code><code>.Name = </code><code>"毅代先锋号一代左部件"</code><code>;</code>
<code>22 }</code>
<code>23 </code><code>public</code> <code>LeftHandComponent(</code><code>string</code> <code>strname)</code>
<code>24 {</code>
<code>25 </code><code>base</code><code>.Name = strname;</code>
<code>26 }</code>
<code>27 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>28 {</code>
<code>29 Console.WriteLine(</code><code>base</code><code>.Name);</code>
<code>30 }</code>
<code>31 }</code>
等等一些部件……
这下我再把原来的搭好的“生产机器”拆了,内部修改一下,来看一下修改后的“机器”
<code>1 </code><code>public</code> <code>class</code> <code>IronManComponentFactory</code>
<code>3 </code><code>public</code> <code>static</code> <code>Component CreateComponent(</code><code>string</code> <code>comname)</code>
<code>5 </code><code>switch</code> <code>(comname)</code>
<code>6 {</code>
<code>7 </code><code>case</code> <code>"RightCom"</code><code>:</code>
<code>8 </code><code>return</code> <code>new</code> <code>RightHandComponent();</code>
<code>9 </code><code>case</code> <code>"LeftCom"</code><code>:</code>
<code>10 </code><code>return</code> <code>new</code> <code>LeftHandComponent();</code>
<code>11</code>
<code>12 }</code>
<code>13 </code><code>return</code> <code>null</code><code>;</code>
<code>14 }</code>
<code>15 }</code>
自己来测试一下:
<code>1 Component rightcomponent = IronManComponentFactory.CreateComponent(</code><code>"RightCom"</code><code>);</code>
<code>2 Component leftcomponent = IronManComponentFactory.CreateComponent(</code><code>"LeftCom"</code><code>);</code>
<code>3 rightcomponent.Self_Described();</code>
<code>4 leftcomponent.Self_Described();</code>
于是,我很放心的就交给了“玩具厂”使用了,还得了个好评。
工厂方法
好景不长,“玩具厂”再次来电,提出一个要求,想让我的“生产机器”里面还可以生产更多的符合“部件规范说明书”的部件。
这样说来是要改装“生产机器”了。 可以说“玩具厂”是故意的,绝对是故意的。这下整蒙圈了,亏血本了,“生产机器”又要拆了…… 直接来看“生产机器”的图纸
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<code>1 </code><code>public</code> <code>abstract</code> <code>class</code> <code>IronManComponentFactory</code>
<code>3 </code><code>protected</code> <code>string</code> <code>factoryName = </code><code>string</code><code>.Empty;</code>
<code>4 </code><code>protected</code> <code>void</code> <code>InitDataMessage()</code>
<code>5 {</code>
<code>6 Console.WriteLine(</code><code>"生产机器:"</code> <code>+ factoryName + </code><code>".准备就绪"</code><code>);</code>
<code>8 </code><code>public</code> <code>abstract</code> <code>Component CreateComponent();</code>
<code>9 }</code>
<code>10 </code><code>public</code> <code>class</code> <code>RightComFactory:IronManComponentFactory</code>
<code>11 {</code>
<code>12</code>
<code>13 </code><code>public</code> <code>override</code> <code>Component CreateComponent()</code>
<code>15 </code><code>base</code><code>.factoryName = </code><code>"右臂部件生产器"</code><code>;</code>
<code>16 InitDataMessage();</code>
<code>17 </code><code>return</code> <code>new</code> <code>RightHandComponent();</code>
<code>18 }</code>
<code>19 }</code>
<code>20 </code><code>public</code> <code>class</code> <code>LeftComFactory:IronManComponentFactory</code>
<code>21 {</code>
<code>22</code>
<code>23 </code><code>public</code> <code>override</code> <code>Component CreateComponent()</code>
<code>25 </code><code>base</code><code>.factoryName = </code><code>"左臂部件生产器"</code><code>;</code>
<code>26 InitDataMessage();</code>
<code>27 </code><code>return</code> <code>new</code> <code>LeftHandComponent();</code>
<code>28 }</code>
<code>29 }</code>
<code>30 </code><code>public</code> <code>class</code> <code>PottingFactrory</code>
<code>31 {</code>
<code>32 </code><code>/// <summary></code>
<code>33 </code><code>/// 取件口</code>
<code>34 </code><code>/// </summary></code>
<code>35 </code><code>/// <param name="comFactory"></param></code>
<code>36 </code><code>/// <returns></returns></code>
<code>37 </code><code>public</code> <code>static</code> <code>Component ComExit(IronManComponentFactory comFactory)</code>
<code>38 {</code>
<code>39 </code><code>if</code> <code>(comFactory != </code><code>null</code><code>)</code>
<code>40 {</code>
<code>41 </code><code>return</code> <code>comFactory.CreateComponent();</code>
<code>42 }</code>
<code>43 </code><code>return</code> <code>null</code><code>;</code>
<code>44 }</code>
<code>45 }</code>

我们通过“取件口”取件
<code>1 Component component = PottingFactrory.ComExit(</code><code>new</code> <code>RightComFactory());</code>
<code>2 component.Self_Described();</code>
我们只要通过更换“生产插件”,从“取件口”获得不同的部件。 或者更改需求,又要生产符合“规范说明书”的另一些产品的时候,可以自定义来实现“生产插件”,插入“生产机器”即可。
这样可以送给“玩具厂”使用了。这次得到了很好的一个评价,我也可以休息一下了。
这里的工厂方法是开闭原则(OCP)的实现,很优雅的显示出了设计原则和设计模式的美。
抽象工厂
“对,没错。‘玩具厂’又来了……。”
这次“玩具厂”是把Iron部件升级了,二代部件出来了,是在一代的基础上做了一些个性化的设计。来看新增部件的“图纸”
<code>1 </code><code>public</code> <code>class</code> <code>RightHandComponent2 : Component</code>
<code>3 </code><code>public</code> <code>RightHandComponent2() : </code><code>this</code><code>(</code><code>"毅代先锋号二代右部件"</code><code>) { }</code>
<code>4 </code><code>public</code> <code>RightHandComponent2(</code><code>string</code> <code>strname)</code>
<code>6 </code><code>base</code><code>.Name = strname;</code>
<code>8 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>10 Console.WriteLine(</code><code>"自描述:我是->"</code> <code>+ </code><code>base</code><code>.Name);</code>
<code>12 }</code>
<code>13</code>
<code>14 </code><code>public</code> <code>class</code> <code>LeftHandComponent2 : Component</code>
<code>15 {</code>
<code>16 </code><code>public</code> <code>LeftHandComponent2() : </code><code>this</code><code>(</code><code>"毅代先锋号一代左部件"</code><code>) { }</code>
<code>17 </code><code>public</code> <code>LeftHandComponent2(</code><code>string</code> <code>strname)</code>
<code>18 {</code>
<code>19 </code><code>base</code><code>.Name = strname;</code>
<code>20 }</code>
<code>21 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>22 {</code>
<code>23 Console.WriteLine(</code><code>"自描述:我是->"</code> <code>+ </code><code>base</code><code>.Name);</code>
<code>24 }</code>
<code>25 }</code>
按照“规范说明书”,添加了两张“图纸”,它们分别是二代的左右手部件。
部件的整体结构没怎么变,但是“生产机器”的“规范说明”就要更改了,以为在上面说到的“生产插件”也要重新更改。
先来看一下“生产机器”的“规范说明”:
<code>1 </code><code>public</code> <code>abstract</code> <code>class</code> <code>IronManComponentFactory</code>
<code>3 </code><code>protected</code> <code>string</code> <code>factoryName = </code><code>string</code><code>.Empty;</code>
<code>4 </code><code>protected</code> <code>void</code> <code>InitDataMessage()</code>
<code>5 {</code>
<code>6 Console.WriteLine(</code><code>"生产机器:"</code> <code>+ factoryName + </code><code>".准备就绪"</code><code>);</code>
<code>7 }</code>
<code>8 </code><code>public</code> <code>abstract</code> <code>Component CreateComponent();</code>
<code>9 </code><code>public</code> <code>abstract</code> <code>Component CreateComponent2();</code>
<code>10</code>
<code>12 }</code>
当然喽,“规范说明”都改了,那上面说过的两个生产插件也得改了:
<code>1 </code><code>public</code> <code>class</code> <code>RightComFactory : IronManComponentFactory </code><code>//右部件生产插件</code>
<code>3</code>
<code>4 </code><code>public</code> <code>override</code> <code>Component CreateComponent()</code>
<code>6 </code><code>base</code><code>.factoryName = </code><code>"新右臂部件生产器"</code><code>;</code>
<code>7 InitDataMessage();</code>
<code>8 </code><code>return</code> <code>new</code> <code>RightHandComponent();</code>
<code>9 }</code>
<code>11 </code><code>public</code> <code>override</code> <code>Component CreateComponent2()</code>
<code>12 {</code>
<code>13 </code><code>base</code><code>.factoryName = </code><code>"新右臂部件生产器"</code><code>;</code>
<code>14 InitDataMessage();</code>
<code>15 </code><code>return</code> <code>new</code> <code>RightHandComponent2();</code>
<code>16 }</code>
<code>17 }</code>
<code>18</code>
<code>19 </code><code>public</code> <code>class</code> <code>LeftComFactory : IronManComponentFactory </code><code>//左部件生产插件</code>
<code>20 {</code>
<code>21</code>
<code>22 </code><code>public</code> <code>override</code> <code>Component CreateComponent()</code>
<code>23 {</code>
<code>24 </code><code>base</code><code>.factoryName = </code><code>"新左臂部件生产器"</code><code>;</code>
<code>25 InitDataMessage();</code>
<code>26 </code><code>return</code> <code>new</code> <code>LeftHandComponent();</code>
<code>27 }</code>
<code>28</code>
<code>29 </code><code>public</code> <code>override</code> <code>Component CreateComponent2()</code>
<code>30 {</code>
<code>31 </code><code>base</code><code>.factoryName = </code><code>"新左臂部件生产器"</code><code>;</code>
<code>32 InitDataMessage();</code>
<code>33 </code><code>return</code> <code>new</code> <code>LeftHandComponent2();</code>
<code>34 }</code>
<code>35 }</code>
所要做的修改都是连带关系,包装”生产机器“的”取件口“也要改:
<code>1 </code><code>public</code> <code>class</code> <code>PottingFactory</code>
<code>3 </code><code>private</code> <code>IronManComponentFactory comFactory = </code><code>null</code><code>;</code>
<code>4</code>
<code>5 </code><code>public</code> <code>IronManComponentFactory ComFactory</code>
<code>6 {</code>
<code>7 </code><code>get</code> <code>{ </code><code>return</code> <code>comFactory; }</code>
<code>8 </code><code>set</code> <code>{ comFactory = value; }</code>
<code>9 }</code>
<code>10 </code><code>public</code> <code>PottingFactory(IronManComponentFactory comFactory)</code>
<code>11 {</code>
<code>12 </code><code>this</code><code>.comFactory = comFactory;</code>
<code>13 }</code>
<code>14 </code><code>/// <summary></code>
<code>15 </code><code>/// 取件口</code>
<code>16 </code><code>/// </summary></code>
<code>17 </code><code>/// <param name="comFactory"></param></code>
<code>18 </code><code>/// <returns></returns></code>
<code>19 </code><code>//public static Component ComExit(IronManComponentFactory comFactory)</code>
<code>20 </code><code>//{</code>
<code>21 </code><code>// if (comFactory != null)</code>
<code>22 </code><code>// {</code>
<code>23 </code><code>// return comFactory.CreateComponent();</code>
<code>24 </code><code>// }</code>
<code>25 </code><code>// return null;</code>
<code>26 </code><code>//}</code>
<code>27 }</code>
到这里就差不多结束了。在工厂方法模式上 做了稍稍的(几乎全改了)改动。
当然自己要先来测试一下喽:
<code>1 PottingFactory pottingfact = </code><code>new</code> <code>PottingFactory(</code><code>new</code> <code>RightComFactory());</code>
<code>2 Component component= pottingfact.ComFactory.CreateComponent();</code>
<code>3 component.Self_Described();</code>
<code>4 component = pottingfact.ComFactory.CreateComponent2();</code>
<code>5 component.Self_Described();</code>
End IronMan之旅才刚刚开始
本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1409120,如需转载请自行联系原作者