通俗易懂設計模式解析——裝飾模式
前言
今天介紹的是結構型設計模式中的——裝飾模式(Decorator Pattern),也是裝飾器模式。裝飾也就是裝點修飾。例如我們對手機進行裝飾,買了一個新的手機,先貼個鋼化膜。在帶一個殼。偶爾還在背面貼點貼紙。裝一些掛件。這些等等行為也就是裝飾。生活中的裝飾是如此,那麼程式設計中的裝飾模式又是如何呢?
裝飾模式介紹
一、來由
在我們平常的軟體系統中,經常會面臨著向現有的物件新增一些新的功能或者新的職責,但是呢?又不能修改現有的類。以往常用的可能是繼承來解決次問題。但是採用繼承來說,隨著擴充套件功能的增加,子類會變化的很膨脹。那麼裝飾器模式呢就解決這麼一個問題,裝飾器模式允許向一個現有的物件新增新的功能職責,同時又不改變其結構。將其功能職責劃分。
二、意圖
動態地給一個物件新增一些額外的職責。就增加功能來說,裝飾器模式相比生成子類更為靈活。
三、案例圖
四、裝飾模式程式碼示例
看上述案例圖,裝飾模式包含以下部分組成:
抽象構件角色:給出一個抽象介面,以規範準備接收新加的責任
具體構件角色:繼承抽象構件角色,定義一個將要接收新加責任的類
裝飾角色:繼承抽象構件角色,包含一個構件角色物件的例項,並且實現抽象構件角色的介面
具體裝飾角色:繼承裝飾角色,負責新加責任。
我們繼續看手機的案例,今天新買了一個手機,需要新加鋼化膜,手機殼,然後才是一個我想要的手機。在這兒之後突然又想加一個掛件增加美感。我們看下如何使用裝飾模式來實現手機裝飾的問題吧:
namespace Decorator_Pattern { class DecoratorPattern { } #region 抽象構件角色——抽象手機(抽象一個介面,準備接收新增的責任)========= /// <summary> /// 手機抽象類 /// </summary> public abstract class Phone { public abstract void Write(); } #endregion #region 具體抽象構件角色——具體手機(實現抽象介面)=============================== public class HuaweiV9Phone : Phone { public override void Write() { Console.WriteLine("對榮耀V9手機開始裝飾"); } } #endregion #region 裝飾抽象角色——繼承抽象構件角色,包含一個抽象構件角色物件的例項 /// <summary> /// 裝飾角色 /// </summary> public abstract class Decorator : Phone { public Phone _phone; protected Decorator(Phone phone) { this._phone = phone; } public override void Write() { if (_phone!=null) { _phone.Write(); } } } #endregion #region 具體裝飾角色——手機加上鋼化膜 /// <summary> /// 具體裝飾角色 /// </summary> public class Membrane : Decorator { public Membrane(Phone phone) : base(phone) { } public override void Write() { base.Write(); AddMembrane(); } public void AddMembrane() { Console.WriteLine("手機加上了鋼化膜!"); } } #endregion #region 具體裝飾角色——手機加上殼 /// <summary> /// 具體裝飾角色 /// </summary> public class Shell : Decorator { public Shell(Phone phone) : base(phone) { } public override void Write() { base.Write(); AddShell(); } public void AddShell() { Console.WriteLine("手機加上了殼!"); } } #endregion #region 具體裝飾角色——手機掛件 /// <summary> /// 具體裝飾角色 /// </summary> public class Pendant : Decorator { public Pendant(Phone phone) : base(phone) { } public override void Write() { base.Write(); AddPendant(); } public void AddPendant() { Console.WriteLine("手機加上了掛件!"); } } #endregion }
class Program { static void Main(string[] args) { //現在獲得了一個手機 Phone phone = new HuaweiV9Phone(); //裸機一個,先貼個膜 Decorator membrane = new Membrane(phone); membrane.Write(); Console.WriteLine(); //還是覺得不順眼,再加個外殼看看 Decorator membraneShell = new Shell(membrane); //現在我同時有鋼化膜和外殼了 membraneShell.Write(); Console.WriteLine( ); //這時候我覺得還是不要外殼了。我需要同時又鋼化膜和手機掛件 Decorator membranePendant = new Pendant(membrane); membranePendant.Write(); Console.WriteLine(); Console.ReadLine(); } }
使用場景及優缺點
一、使用場景
1、需要擴充套件類的功能或者為類增加新增的責任
2、需要動態增加功能或者撤銷功能
二、優點
1、裝飾類與被裝飾類可以獨立發展,不會互相耦合, 極易擴充套件、符合開閉原則
2、裝飾模式與繼承關係的目的都是要擴充套件物件的功能,但是裝飾模式可以提供比繼承更多的靈活性。
三、缺點
1、增加系統複雜度,更加易於出錯,難於排查錯誤。增大了學習與理解的難度。
總結
裝飾模式到這裡就短暫的介紹完了。在平常中,裝飾模式使用的情況較多。一般來說,我們擴充套件一個類經常選擇繼承的方式,但是由於繼承是為類引入靜態的特徵。並且隨著功能增加的越來越多,子類會越來越膨脹。裝飾模式是可以替代繼承方式的。前面結構型的設計模式也學習了介面卡模式與橋接模式。再加上今天學習的裝飾模式。我們都需要細細分析其區別及使用場景,以便於後期使用時不至於混淆其用法。要用的恰到好處。
只有經歷過地獄般的折磨,才有征服天堂的力量。只有流過血的手指才能彈出世間的絕唱。
C#設計模式系列目錄
歡迎大家掃描下方二維碼,和我一起踏上設計模式的闖關之路吧!