今天介紹的是結構型設計模式中的——裝飾模式(Decorator Pattern),也是裝飾器模式。裝飾也就是裝點修飾。例如咱們對手機進行裝飾,買了一個新的手機,先貼個鋼化膜。在帶一個殼。偶爾還在背面貼點貼紙。裝一些掛件。這些等等行爲也就是裝飾。生活中的裝飾是如此,那麼編程中的裝飾模式又是如何呢?html
在咱們日常的軟件系統中,常常會面臨着向現有的對象添加一些新的功能或者新的職責,可是呢?又不能修改現有的類。以往經常使用的多是繼承來解決次問題。可是採用繼承來講,隨着擴展功能的增長,子類會變化的很膨脹。那麼裝飾器模式呢就解決這麼一個問題,裝飾器模式容許向一個現有的對象添加新的功能職責,同時又不改變其結構。將其功能職責劃分。編程
動態地給一個對象添加一些額外的職責。就增長功能來講,裝飾器模式相比生成子類更爲靈活。設計模式
看上述案例圖,裝飾模式包含如下部分組成:ide
抽象構件角色:給出一個抽象接口,以規範準備接收新加的責任學習
具體構件角色:繼承抽象構件角色,定義一個將要接收新加責任的類this
裝飾角色:繼承抽象構件角色,包含一個構件角色對象的實例,而且實現抽象構件角色的接口spa
具體裝飾角色:繼承裝飾角色,負責新加責任。設計
咱們繼續看手機的案例,今天新買了一個手機,須要新加鋼化膜,手機殼,而後纔是一個我想要的手機。在這兒以後忽然又想加一個掛件增長美感。咱們看下如何使用裝飾模式來實現手機裝飾的問題吧:3d
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(); } }
一、須要擴展類的功能或者爲類增長新增的責任code
二、須要動態增長功能或者撤銷功能
一、裝飾類與被裝飾類能夠獨立發展,不會互相耦合, 極易擴展、符合開閉原則
二、裝飾模式與繼承關係的目的都是要擴展對象的功能,可是裝飾模式能夠提供比繼承更多的靈活性。
一、增長系統複雜度,更加易於出錯,難於排查錯誤。增大了學習與理解的難度。
裝飾模式到這裏就短暫的介紹完了。在日常中,裝飾模式使用的狀況較多。通常來講,咱們擴展一個類常常選擇繼承的方式,可是因爲繼承是爲類引入靜態的特徵。而且隨着功能增長的愈來愈多,子類會愈來愈膨脹。裝飾模式是能夠替代繼承方式的。前面結構型的設計模式也學習了適配器模式與橋接模式。再加上今天學習的裝飾模式。咱們都須要細細分析其區別及使用場景,以便於後期使用時不至於混淆其用法。要用的恰到好處。
只有經歷過地獄般的折磨,纔有征服天堂的力量。只有流過血的手指才能彈出世間的絕唱。
歡迎你們掃描下方二維碼,和我一塊兒踏上設計模式的闖關之路吧!