1. 裝飾模式簡介
裝飾模式動態地給一個物件新增額外的職責。例如一幅畫有沒有畫框都可以掛在牆上,畫就是被裝飾者。但是通常都是有畫框的。在掛在牆上之前,畫可以被蒙上玻璃,裝到框子裡,所以在畫上加一層畫框,並把它們組合成一個整體——有框的畫。這樣隨著不斷有新的裝飾的加入,就給商品不斷地打上包裝,變成一個功能更讓人滿意的商品。這種不斷打包裝的過程就是裝飾。
1.1 定義
裝飾模式提供了一種給類增加功能的方法。它通過動態地組合物件,可以給原有的類新增新的程式碼,而無須修改現有程式碼。因此引入bug或產生意外副作用的機會將大幅度減少。
1.2 使用頻率
中等
2. 裝飾模式結構圖
2.1 結構圖
2.2 參與者
裝飾模式參與者:
◊ Component:定義一個物件介面,可以給這些物件動態地新增職責
◊ ConcreteComponent:定義一個物件,可以給這個物件新增一些職責
◊ Decorator:維持一個指向Component的指標,並定義一個與Component介面一致的介面
◊ ConcreteDecorator:負責向ConcreteComponent新增功能
在裝飾模式中,Decorator定義了一個裝飾介面類。因為Decorator與ConcreteComponent繼承同一個介面,所以繼承Decorator的類ConcreteDecorator可以使用ConcreteComponent的方法,再在ConcreteDecorator裡面加入一些新的方法,也就是裝飾,就成為了一個包裝好的裝飾類。
3、裝飾模式結構實現
Component.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.DecoratorPattern.Structural { public abstract class Component { public abstract void Operation(); } }
ConcreteComponent.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.DecoratorPattern.Structural { public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("ConcreteComponent.Operation()"); } } }
Decorator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.DecoratorPattern.Structural { public abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } }
ConcreteDecoratorA.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.DecoratorPattern.Structural { public class ConcreteDecoratorA : Decorator { public override void Operation() { base.Operation(); Console.WriteLine("ConcreteDecoratorA.Operation()"); } } }
ConcreteDecoratorB.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.DecoratorPattern.Structural { public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("ConcreteDecoratorB.Operation()"); } void AddedBehavior() { } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.DecoratorPattern.Structural; namespace DesignPatterns.DecoratorPattern { class Program { static void Main(string[] args) { // Create ConcreteComponent and two Decorators ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); // Link decorators d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); } } }
執行輸出:
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()
請按任意鍵繼續. . .
4、裝飾模式應用分析
裝飾模式適用情形:
◊ 在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責
◊ 處理那些可以撤銷的職責
裝飾模式的特點:
◊ 比靜態類更靈活。使用裝飾模式可以很容易地向物件新增職責的方式。可以用新增和分離的方法,對裝飾在執行時新增和刪除職責。相比之下,繼承機制要求為每個新增的職責建立一個新的子類。這會產生很多新的類,並會增加系統的複雜度。
◊ 使用裝飾模式可以很容易地重複新增一個特性,而兩次繼承特性類則極容易出錯。
◊ 為了避免處理頂層的類有太多的特徵。裝飾模式下,你可以定義一個簡單的類,並用裝飾類給它逐漸地新增功能。這樣可以從簡單的部件組合出複雜的功能,具有低依賴性和地複雜性。
◊ 有許多小物件。採用裝飾模式進行系統設計往往會產生許多看上去類似的小物件,儘管對於瞭解這些系統的人來說,很容易進行定製,但是很難學習這些系統,排錯很惡化呢困難。