前言
今天介紹的是結(jié)構(gòu)型設(shè)計模式中的——裝飾模式(Decorator
Pattern),也是裝飾器模式。裝飾也就是裝點(diǎn)修飾。例如我們對手機(jī)進(jìn)行裝飾,買了一個新的手機(jī),先貼個鋼化膜。在帶一個殼。偶爾還在背面貼點(diǎn)貼紙。裝一些掛件。這些等等行為也就是裝飾。生活中的裝飾是如此,那么編程中的裝飾模式又是如何呢?
裝飾模式介紹
一、來由
在我們平常的軟件系統(tǒng)中,經(jīng)常會面臨著向現(xiàn)有的對象添加一些新的功能或者新的職責(zé),但是呢?又不能修改現(xiàn)有的類。以往常用的可能是繼承來解決次問題。但是采用繼承來說,隨著擴(kuò)展功能的增加,子類會變化的很膨脹。那么裝飾器模式呢就解決這么一個問題,裝飾器模式允許向一個現(xiàn)有的對象添加新的功能職責(zé),同時又不改變其結(jié)構(gòu)。將其功能職責(zé)劃分。
二、意圖
動態(tài)地給一個對象添加一些額外的職責(zé)。就增加功能來說,裝飾器模式相比生成子類更為靈活。
三、案例圖
?
?
?
四、裝飾模式代碼示例
看上述案例圖,裝飾模式包含以下部分組成:
抽象構(gòu)件角色:給出一個抽象接口,以規(guī)范準(zhǔn)備接收新加的責(zé)任
具體構(gòu)件角色:繼承抽象構(gòu)件角色,定義一個將要接收新加責(zé)任的類
裝飾角色:繼承抽象構(gòu)件角色,包含一個構(gòu)件角色對象的實例,并且實現(xiàn)抽象構(gòu)件角色的接口
具體裝飾角色:繼承裝飾角色,負(fù)責(zé)新加責(zé)任。
?
我們繼續(xù)看手機(jī)的案例,今天新買了一個手機(jī),需要新加鋼化膜,手機(jī)殼,然后才是一個我想要的手機(jī)。在這兒之后突然又想加一個掛件增加美感。我們看下如何使用裝飾模式來實現(xiàn)手機(jī)裝飾的問題吧:
?
namespace Decorator_Pattern { class DecoratorPattern { } #region
抽象構(gòu)件角色——抽象手機(jī)(抽象一個接口,準(zhǔn)備接收新增的責(zé)任)=========/// <summary> /// 手機(jī)抽象類 /// </summary>
public abstract class Phone { public abstract void Write(); } #endregion #region
具體抽象構(gòu)件角色——具體手機(jī)(實現(xiàn)抽象接口)===============================public class
HuaweiV9Phone : Phone {public override void Write() { Console.WriteLine("
對榮耀V9手機(jī)開始裝飾"); } } #endregion #region 裝飾抽象角色——繼承抽象構(gòu)件角色,包含一個抽象構(gòu)件角色對象的實例 ///
<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 具體裝飾角色——手機(jī)加上鋼化膜 /// <summary> /// 具體裝飾角色 /// </summary>
public class Membrane : Decorator { public Membrane(Phone phone) : base(phone)
{ }public override void Write() { base.Write(); AddMembrane(); } public void
AddMembrane() { Console.WriteLine("手機(jī)加上了鋼化膜!"); } } #endregion #region
具體裝飾角色——手機(jī)加上殼/// <summary> /// 具體裝飾角色 /// </summary> public class Shell :
Decorator {public Shell(Phone phone) : base(phone) { } public override void
Write() {base.Write(); AddShell(); } public void AddShell() { Console.WriteLine(
"手機(jī)加上了殼!"); } } #endregion #region 具體裝飾角色——手機(jī)掛件 /// <summary> /// 具體裝飾角色 ///
</summary> public class Pendant : Decorator { public Pendant(Phone phone) : base
(phone) { }public override void Write() { base.Write(); AddPendant(); } public
void AddPendant() { Console.WriteLine("手機(jī)加上了掛件!"); } } #endregion }
?
class Program { static void Main(string[] args) { //現(xiàn)在獲得了一個手機(jī) Phone phone = new
HuaweiV9Phone();//裸機(jī)一個,先貼個膜 Decorator membrane = new Membrane(phone);
membrane.Write(); Console.WriteLine();//還是覺得不順眼,再加個外殼看看 Decorator membraneShell
=new Shell(membrane); //現(xiàn)在我同時有鋼化膜和外殼了 membraneShell.Write();
Console.WriteLine( );//這時候我覺得還是不要外殼了。我需要同時又鋼化膜和手機(jī)掛件 Decorator membranePendant =
new Pendant(membrane); membranePendant.Write(); Console.WriteLine();
Console.ReadLine(); } }
?
使用場景及優(yōu)缺點(diǎn)
一、使用場景
1、需要擴(kuò)展類的功能或者為類增加新增的責(zé)任
2、需要動態(tài)增加功能或者撤銷功能
二、優(yōu)點(diǎn)
1、裝飾類與被裝飾類可以獨(dú)立發(fā)展,不會互相耦合, 極易擴(kuò)展、符合開閉原則
2、裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
三、缺點(diǎn)
1、增加系統(tǒng)復(fù)雜度,更加易于出錯,難于排查錯誤。增大了學(xué)習(xí)與理解的難度。
總結(jié)
裝飾模式到這里就短暫的介紹完了。在平常中,裝飾模式使用的情況較多。一般來說,我們擴(kuò)展一個類經(jīng)常選擇繼承的方式,但是由于繼承是為類引入靜態(tài)的特征。并且隨著功能增加的越來越多,子類會越來越膨脹。裝飾模式是可以替代繼承方式的。前面結(jié)構(gòu)型的設(shè)計模式也學(xué)習(xí)了適配器模式與橋接模式。再加上今天學(xué)習(xí)的裝飾模式。我們都需要細(xì)細(xì)分析其區(qū)別及使用場景,以便于后期使用時不至于混淆其用法。要用的恰到好處。
只有經(jīng)歷過地獄般的折磨,才有征服天堂的力量。只有流過血的手指才能彈出世間的絕唱。
C#設(shè)計模式系列目錄 <https://www.cnblogs.com/hulizhong/p/11394686.html>
歡迎大家掃描下方二維碼,和我一起踏上設(shè)計模式的闖關(guān)之路吧!
熱門工具 換一換