c#設計模式之裝飾器模式(Decorator Pattern)


引子

在面向對象語言中,我們常常會聽到這樣一句話:組合優於繼承.那么該如何去理解這句話呢?

下面我將以游戲裝備為模型用簡單的代碼去展示它

先創建一個裝備的抽象類,然后創建刀槍2個具體的業務子類

 1  public abstract class AbstractEquipment
 2     {
 3         public int Id { get; set; }
 4 
 5         public string Name { get; set; }
 6 
 7         public abstract void Attack();
 8     }
 9 
10     public class Gun : AbstractEquipment
11     {
12         public override void Attack()
13         {
14             Console.WriteLine("用槍攻擊");
15         }
16     }
17 
18     class Sword : AbstractEquipment
19     {
20         public override void Attack()
21         {
22             Console.WriteLine("用劍攻擊");
23         }
24     }

面對這樣的場景,我們常常會提出這樣的疑問:如何面對業務擴展?例如,此時需要添加一個新的功能:在裝備攻擊后,會提醒善惡值增加

在不修改業務子類的前提下,我們通過繼承和組合兩種不同的方式來解決,如下:

 1   //繼承
 2     public class GunInherit:Gun
 3     {
 4         public override void Attack()
 5         {
 6             base.Attack();
 7             Console.WriteLine("善惡值增加");
 8         }
 9     }
10     
11     //組合
12     public class EquipmentCombination
13     {
14         private AbstractEquipment _equipment = null;
15         public EquipmentCombination(AbstractEquipment equipment)
16         {
17             _equipment = equipment;
18         }
19 
20         public void Attack()
21         {
22             _equipment.Attack();
23             Console.WriteLine("善惡值增加");
24         }
25     }

觀察上述代碼可以得到以下結論

繼承:雖然代碼少,但是強侵入,強關聯,只能為特定類服務

組合:雖然加了一個全新類,增加了代碼量,但是非常靈活

在這么少量的代碼下,已經能夠看到繼承的劣勢,那么隨着功能需求的增加,僅僅靠繼承來擴展業務,那將會帶來巨大的弊端.

 裝飾器模式

裝飾器模式是通過上述組合加繼承的方式,動態的為業務類添加功能的一種設計模式

在這種設計模式之下,只需要添加一個新的裝飾器,即可為業務類添加一個新的功能

首先對裝飾器進行一次抽象,相比於單單組合的方式,這樣可以減少代碼復雜程度

 1      public class BaseEquipmentDecorator : AbstractEquipment
 2     {
 3         private AbstractEquipment _equipment = null;
 4         public BaseEquipmentDecorator(AbstractEquipment equipment)
 5         {
 6             _equipment = equipment;
 7         }
 8         public override void Attack()
 9         {
10             _equipment.Attack();
11         }
12     }

一旦業務類需要添加新功能,只需要繼承上面的裝飾器基類,加上新功能即可,例如:為裝備添加強化的功能

 1     public class EquipmentStrengthenDecorator:BaseEquipmentDecorator
 2     {
 3         //調用直接父類的指定構造函數
 4         public EquipmentStrengthenDecorator(AbstractEquipment equipment)
 5             :base(equipment)
 6         {
 7 
 8         }
 9         public override void Attack()
10         {
11             base.Attack();
12             Strengthen();
13         }
14         public void Strengthen()
15         {
16             Console.WriteLine("武器被強化");
17         }
18     }

調用:

    class Program
    {
        static void Main(string[] args)
        {
            AbstractEquipment gun = new Gun();
            gun = new EquipmentStrengthenDecorator(gun);
            gun.Attack();
            Console.ReadKey();
        }
    }

打印:

用槍攻擊

武器被強化

這樣,強化的功能就添加到了裝備之中了

通過繼承加組合的裝飾器模式,我們可以靈活的動態添加對象的功能職責

裝飾器模式類圖

裝飾器模式4種角色:

抽象業務角色(AbstractEquipment):具體業務類的抽象;

具體業務角色(Gun,Sword):具體業務類,被裝飾的直接對象;

裝飾器基類角色(BaseEquipmentDecorator):具體裝飾器的基類;

具體裝飾器角色(EquipmentStrengthenDecorator):提供具體的功能去裝飾具體業務角色;

裝飾器模式優缺點及使用場景

優點:靈活,擴展性好,能夠在不影響業務類的前提下,動態的為其添加本身不存在的功能

缺點:增加了程序的復雜程度

使用場景:為具體的業務對象附加功能職責,例如上述的游戲裝備,以及培訓班的各層vip,商場的多重優惠等等

 

出自:博客園-半路獨行

原文地址:https://www.cnblogs.com/banluduxing/p/9152453.html

本文出自於http://www.cnblogs.com/banluduxing 轉載請注明出處。

代碼地址:https://github.com/weiweu/My-space/tree/master/Design/DecoratorPattern


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM