天天看點

C#設計模式之裝飾者

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

<code>6         </code><code>/// 名稱</code>

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

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

<code>15         </code><code>/// &lt;/summary&gt;</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>"自描述:我是-&gt;"</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>"自描述:我是-&gt;"</code> <code>+ </code><code>base</code><code>.Name);</code>

<code>40         }</code>

<code>41     }</code>

武器的:

(這裡的結構經過簡化,跟上個篇幅沒有聯系,感興趣的朋友可以按照上個篇幅的"武器"結構來設計)

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

<code>2     </code><code>/// 武器</code>

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

<code>4     </code><code>public</code> <code>abstract</code> <code>class</code> <code>Weapon</code>

<code>5     {</code>

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

<code>7         </code><code>/// 攻擊</code>

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

<code>9         </code><code>public</code> <code>abstract</code> <code>void</code> <code>Attack();</code>

<code>10     }</code>

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

<code>12     </code><code>/// 雷射武器</code>

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

<code>23     </code><code>/// 飛彈武器</code>

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

<code>17     </code><code>/// ***</code>

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

<code>31     </code><code>/// 錘子</code>

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

C#設計模式之裝飾者

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

END

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