1. 程式人生 > 其它 >設計模式之裝飾模式

設計模式之裝飾模式

前言

這裡先舉兩個生活中的小栗子:

  • 新房的裝修,房屋裝修並沒有改變房屋居住的本質,但可以讓房屋變得更漂亮,更溫馨,更實用,更滿足居家需求。
  • 穿搭衣服,你可以根據天氣氣候變化,選擇穿毛衣,穿羽絨服。也可以根據出行場合選擇西裝等等。

在軟體設計中,類似上面的場景我們也可以把物件在不改變結構的情況下對其加工擴充套件修飾,使得物件具有更加強大的功能,這種技術在設計模式中就叫裝飾模式。裝飾模式可以在不改變一個物件本身功能的基礎上給物件增加額外的新行為。

裝飾模式定義

裝飾模式:動態地給一個物件增加一些額外的職責。就擴充套件功能面言,裝飾模式提供了—種比使用子類更加靈活的替代方案。

裝飾模式是一種結構型設計模式, 允許你通過將物件放入包含行為的特殊封裝物件中來為原物件繫結新的行為。

程式碼實現

類圖結構

標準的裝飾模式應該包含如下4個角色(也可根據實際情況定義):

  • Componcnt(抽象構建):它是具體構建和抽象裝飾類的共同父類,聲明瞭在具體構件中實轟的業務方法,它的引入可以使客戶以一致的方式處理未被裝飾的物件以及裝飾之後的物件。
  • ConcreteComponent(具體構建):它是抽象構件類的子類,用於定義具體的構件物件,實現了在抽象物件中宣告的方法,裝飾類可以給它增加額外的職責(方法)。
  • Decorater(抽象裝飾類):它也是抽象構件類的子類,用於給具體構件增加職責,但是具體職責通常在其子類中實現,它維護一個指向抽象構件物件的引用,通過該引用可以呼叫裝飾之前構件物件的方法,並通過其子面擴充套件該方法,以達到裝飾的目的。
  • ConcerteDecorater(具體裝飾類):它也是抽象裝飾類的子類,負責向構建新增新的職責,每一個具體裝飾類都定義了一系列新的行為,它可以呼叫再抽象裝飾類中定義的方法,並且可以增加新的方法,以實現擴充套件物件的行為。

裝飾模式的實現

  1. 抽象構建類,一般設計為抽象類或者介面,在其中宣告抽象的業務方法,也可以在抽象構建中實現一些共有的業務方法。
  2. 具體構建類,繼承抽象構建類,一般用作提供基本功能的實現
  3. 抽象裝飾類,抽象模式的核心也就在這裡,其典型程式碼如下
public class Decorator : Person
    {
        private readonly Person _person;
        public Decorator(Person person)
        {
            _person = person;
        }

        public override void Show()
        {
            if (_person != null)
            {
                _person.Show();
            }
        }
    }
  1. 具體裝飾類,繼承抽象裝飾類,可以在此對其進行擴充套件,例如
 public class ConcernTshirt : Decorator
    {
        public ConcernTshirt(Person person) : base(person)
        {

        }

        public override void Show()
        {
            base.Show();
            Console.WriteLine("T恤");
            Necktie();
        }

        private void Necktie()
        {
            Console.WriteLine("領帶");
        }
    }

優點和缺點以及使用場景

優點

  • 擴充套件性:無需建立新子類即可擴充套件物件的行為
  • 任意組裝:可以用多個裝飾封裝物件來組合幾種行為
  • 可維護性:可以將同行為的一個大類拆分成多個較小的類

缺點

  • 各層初始化配置看起來有點糟糕
  • 因為可以隨意裝配,也就意味著順序可能不那麼同一,易於出錯,排錯也困難,對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為繁瑣

使用場景

  • 如果希望在無需修改程式碼的情況下即可使用物件,且希望在執行時為物件新增額外的行為,可以使用裝飾模式。
  • 如果用繼承來擴充套件物件行為的方案難以實現或者根本不可行, 你可以使用該模式。

示例程式碼

原始碼倉庫地址:https://github.com/luchong0813/DesignModel