1. 程式人生 > >通俗易懂設計模式解析——裝飾模式

通俗易懂設計模式解析——裝飾模式

前言

  今天介紹的是結構型設計模式中的——裝飾模式(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#設計模式系列目錄

歡迎大家掃描下方二維碼,和我一起踏上設計模式的闖關之路吧!