IronMan之裝飾者
上一篇的文章我們講到要給"IronMan"配備"武器",并且還使用了"武器",效果還是不錯的,對于多種環境、多種攻擊方式的"武器"使用,我們已經掌握了。 有的朋友沒有看過上一篇文章,那也沒關系,此篇的重點不會涉及到上一篇的内容。
好吧,廢話不多說,直接進入正題, 這裡簡要的介紹下,本人一直在為一家"玩具廠"服務,緻力于"IronMan"(鋼鐵俠)的研究,前面的幾個篇幅都是在介紹怎麼去合理的生産組成"IronMan"的"部件",以及最近需求的變更,需要"部件"可攜帶武器,并且能攻擊,于是在上一篇中講到了"武器"的使用,感興趣的朋友可以去看看。 那我們要如何的去把"武器"和"部件"整合在一起呢?
先來看一下本篇篇幅要用到的一些"部件"和"武器"的結構, 部件的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<code>1 </code><code>public</code> <code>abstract</code> <code>class</code> <code>Component</code>
<code>2 {</code>
<code>3 </code><code>///之間的代碼于本篇幅無關</code>
<code>4 </code><code>private</code> <code>string</code> <code>strName = </code><code>string</code><code>.Empty;</code>
<code>5 </code><code>/// <summary></code>
<code>6 </code><code>/// 名稱</code>
<code>7 </code><code>/// </summary></code>
<code>8 </code><code>public</code> <code>string</code> <code>Name</code>
<code>9 {</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>/// <summary></code>
<code>14 </code><code>/// 自我描述</code>
<code>15 </code><code>/// </summary></code>
<code>16 </code><code>public</code> <code>abstract</code> <code>void</code> <code>Self_Described();</code>
<code>17 }</code>
<code>18 </code><code>public</code> <code>class</code> <code>RightHandComponent : Component</code>
<code>19 {</code>
<code>20 </code><code>public</code> <code>RightHandComponent() : </code><code>this</code><code>(</code><code>"毅代先鋒号一代右部件"</code><code>) { }</code>
<code>21 </code><code>public</code> <code>RightHandComponent(</code><code>string</code> <code>strname)</code>
<code>22 {</code>
<code>23 </code><code>base</code><code>.Name = strname;</code>
<code>24 }</code>
<code>25 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>26 {</code>
<code>27 Console.WriteLine(</code><code>"自描述:我是->"</code> <code>+ </code><code>base</code><code>.Name);</code>
<code>28 }</code>
<code>29 }</code>
<code>30 </code><code>public</code> <code>class</code> <code>LeftHandComponent : Component</code>
<code>31 {</code>
<code>32 </code><code>public</code> <code>LeftHandComponent() : </code><code>this</code><code>(</code><code>"毅代先鋒号一代左部件"</code><code>) { }</code>
<code>33 </code><code>public</code> <code>LeftHandComponent(</code><code>string</code> <code>strname)</code>
<code>34 {</code>
<code>35 </code><code>base</code><code>.Name = strname;</code>
<code>36 }</code>
<code>37 </code><code>public</code> <code>override</code> <code>void</code> <code>Self_Described()</code>
<code>38 {</code>
<code>39 Console.WriteLine(</code><code>"自描述:我是->"</code> <code>+ </code><code>base</code><code>.Name);</code>
<code>40 }</code>
<code>41 }</code>
武器的:
(這裡的結構經過簡化,跟上個篇幅沒有聯系,感興趣的朋友可以按照上個篇幅的"武器"結構來設計)
<code>1 </code><code>/// <summary></code>
<code>2 </code><code>/// 武器</code>
<code>3 </code><code>/// </summary></code>
<code>4 </code><code>public</code> <code>abstract</code> <code>class</code> <code>Weapon</code>
<code>5 {</code>
<code>6 </code><code>/// <summary></code>
<code>7 </code><code>/// 攻擊</code>
<code>8 </code><code>/// </summary></code>
<code>9 </code><code>public</code> <code>abstract</code> <code>void</code> <code>Attack();</code>
<code>10 }</code>
<code>11 </code><code>/// <summary></code>
<code>12 </code><code>/// 雷射武器</code>
<code>13 </code><code>/// </summary></code>
<code>14 </code><code>public</code> <code>class</code> <code>LaserWeapon : Weapon</code>
<code>15 {</code>
<code>16 </code><code>public</code> <code>override</code> <code>void</code> <code>Attack()</code>
<code>17 {</code>
<code>18 </code><code>//LaserAttack</code>
<code>19 Console.WriteLine(</code><code>"雷射武器"</code><code>);</code>
<code>20 }</code>
<code>21 }</code>
<code>22 </code><code>/// <summary></code>
<code>23 </code><code>/// 飛彈武器</code>
<code>24 </code><code>/// </summary></code>
<code>25 </code><code>public</code> <code>class</code> <code>MissileWeapon : Weapon</code>
<code>26 {</code>
<code>27 </code><code>public</code> <code>override</code> <code>void</code> <code>Attack()</code>
<code>28 {</code>
<code>29 </code><code>//MissileAttack</code>
<code>30 Console.WriteLine(</code><code>"飛彈武器"</code><code>);</code>
<code>31 }</code>
<code>32 }</code>
看到這樣的結構,會想說怎麼去為"部件"提供額外的功能呢?讓各種武器繼承自"部件"?N種武器怎麼辦?那"部件"的結構是多麼大啊!!!想一下都覺得可怕。
不過還好,有設計模式的存在,在這種特定的情況下首先想到的就是"裝飾者"模式。 舊版的"部件"和"武器"已經滿足不了現在的需求了(可以滿足,但是這樣整合起來顯得過于複雜和龐大,對于初學者可能不太容易學習,是以這裡這樣說)。 我們重新來更新"部件"和"武器"的結構:
<code>2 </code><code>/// 新更新的武器規範</code>
<code>4 </code><code>public</code> <code>interface</code> <code>IWeaponUpgrade</code>
<code>7 </code><code>/// 是武器了,當然要具備攻擊性了,不然也不叫武器</code>
<code>9 </code><code>void</code> <code>Attack();</code>
<code>12 </code><code>/// 新更新的部件 支援攜帶武器(因為已經支援攜帶了武器,它自然而然的也歸納與武器一類)</code>
<code>13 </code><code>/// 此部件為簡化版(便于學習)——。</code>
<code>14 </code><code>/// </summary></code>
<code>15 </code><code>public</code> <code>class</code> <code>ComUpgrade:IWeaponUpgrade</code>
<code>16 {</code>
<code>17 </code><code>public</code> <code>void</code> <code>Attack()</code>
<code>18 {</code>
<code>19 Console.WriteLine(</code><code>"IronMan的某部件開始輸出攻擊:"</code><code>);</code>
42
43
<code>2 </code><code>/// 武器包裝器,主動性攻擊武器要實作。功能:可以塞入任何武器類型,并且使得塞入的武器獲得此武器(可是實作了此類的子類)的功能</code>
<code>4 </code><code>public</code> <code>class</code> <code>WeaponDecorator : IWeaponUpgrade</code>
<code>6 </code><code>protected</code> <code>IWeaponUpgrade weaponUpgrade;</code>
<code>7 </code><code>public</code> <code>WeaponDecorator(IWeaponUpgrade weapon)</code>
<code>8 {</code>
<code>9 </code><code>this</code><code>.weaponUpgrade = weapon;</code>
<code>10 }</code>
<code>11 </code><code>public</code> <code>virtual</code> <code>void</code> <code>Attack()</code>
<code>12 {</code>
<code>13 </code><code>this</code><code>.weaponUpgrade.Attack();</code>
<code>14 }</code>
<code>15 }</code>
<code>16 </code><code>/// <summary></code>
<code>17 </code><code>/// ***</code>
<code>18 </code><code>/// </summary></code>
<code>19 </code><code>public</code> <code>class</code> <code>Knife : WeaponDecorator</code>
<code>20 {</code>
<code>21 </code><code>public</code> <code>Knife(IWeaponUpgrade weapon)</code>
<code>22 : </code><code>base</code><code>(weapon)</code>
<code>23 { }</code>
<code>24 </code><code>public</code> <code>override</code> <code>void</code> <code>Attack()</code>
<code>25 {</code>
<code>26 </code><code>base</code><code>.Attack();</code>
<code>27 Console.WriteLine(</code><code>"***攻擊"</code><code>);</code>
<code>30 </code><code>/// <summary></code>
<code>31 </code><code>/// 錘子</code>
<code>32 </code><code>/// </summary></code>
<code>33 </code><code>public</code> <code>class</code> <code>Hammer : WeaponDecorator</code>
<code>34 {</code>
<code>35 </code><code>public</code> <code>Hammer(IWeaponUpgrade weapon)</code>
<code>36 : </code><code>base</code><code>(weapon)</code>
<code>37 { }</code>
<code>38 </code><code>public</code> <code>override</code> <code>void</code> <code>Attack()</code>
<code>39 {</code>
<code>40 </code><code>base</code><code>.Attack();</code>
<code>41 Console.WriteLine(</code><code>"錘子攻擊"</code><code>);</code>
<code>42 }</code>
<code>43 }</code>
<code>1 ComUpgrade comupgrade = </code><code>new</code> <code>ComUpgrade();</code>
<code>2 Knife knife = </code><code>new</code> <code>Knife(comupgrade);</code>
<code>3 Hammer hammer = </code><code>new</code> <code>Hammer(knife);</code>
<code>4 hammer.Attack();</code>

這樣的結構就是比較完美的了,"部件"(也就是被動武器)的變化或者是裝飾武器(主動性武器)的變化兩者間是不會受影響的,可以随便新增新的"武器"到"部件"上,而且裝飾武器之間也是可以互相裝飾的,對于擴充"部件"的功能,這種方式比繼承漂亮多了。細心的人會發現,還有跟裝飾的順序有關系,是這樣的。 對于功能的擴充或許展現不出來裝飾順序的優美,但是在業務流程的需求裡就能展現了,這一點就好比是那種業務鍊,比如是:網上商場的業務,選擇商品->加入購物車->付款(這裡隻是舉例),這樣的一條業務,也可以是 選擇商品->付款,是的,都是可以直接付款的,這裡就可以把“加入購物車”、“付款”定義為裝飾者對象,可以把使用者資訊定義為被裝飾者,可以是“加入購物車”然後再“付款”,也可是直接“付款”,想想看這樣用裝飾者模式是不是很簡單的就實作了。
END
本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1412747,如需轉載請自行聯系原作者