引子
在面向對象語言中,我們常常會聽到這樣一句話:組合優於繼承.那么該如何去理解這句話呢?
下面我將以游戲裝備為模型用簡單的代碼去展示它
先創建一個裝備的抽象類,然后創建刀槍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