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,如需轉載請自行聯系原作者