天天看點

C#設計模式之工廠

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>/// &lt;summary&gt;</code>

<code>5         </code><code>/// 名稱</code>

<code>6         </code><code>/// &lt;/summary&gt;</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>/// &lt;summary&gt;</code>

<code>13         </code><code>/// 自我描述</code>

<code>14         </code><code>/// &lt;/summary&gt;</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>/// &lt;summary&gt;</code>

<code>33         </code><code>/// 取件口</code>

<code>34         </code><code>/// &lt;/summary&gt;</code>

<code>35         </code><code>/// &lt;param name="comFactory"&gt;&lt;/param&gt;</code>

<code>36         </code><code>/// &lt;returns&gt;&lt;/returns&gt;</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>

C#設計模式之工廠

我們通過“取件口”取件

<code>1 Component component = PottingFactrory.ComExit(</code><code>new</code> <code>RightComFactory());</code>

<code>2 component.Self_Described();</code>

C#設計模式之工廠

我們隻要通過更換“生産插件”,從“取件口”獲得不同的部件。 或者更改需求,又要生産符合“規範說明書”的另一些産品的時候,可以自定義來實作“生産插件”,插入“生産機器”即可。

這樣可以送給“玩具廠”使用了。這次得到了很好的一個評價,我也可以休息一下了。

這裡的工廠方法是開閉原則(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>"自描述:我是-&gt;"</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>"自描述:我是-&gt;"</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>/// &lt;summary&gt;</code>

<code>15        </code><code>/// 取件口</code>

<code>16        </code><code>/// &lt;/summary&gt;</code>

<code>17        </code><code>/// &lt;param name="comFactory"&gt;&lt;/param&gt;</code>

<code>18        </code><code>/// &lt;returns&gt;&lt;/returns&gt;</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>

C#設計模式之工廠

End IronMan之旅才剛剛開始

     本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1409120,如需轉載請自行聯系原作者