1.概述 裝飾者模式,英文名叫做Decorator Pattern。裝飾模式是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。 2.特點 (1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以和真實對象相同的方式和裝飾對象交互。 (2) 裝飾對象包含一個真實對象的引用(reference) (3) 裝飾對象接受所有來自客戶端的請求。它把這些請求轉發給真實的對象。 (4) 裝飾對象可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。 3.應用范圍 1. 需要擴展一個類的功能,或給一個類添加附加職責。 2. 需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。 3. 需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關系變的不現實。 4. 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。 4.優點 1. Decorator模式與繼承關系的目的都是要擴展對象的功能,但是Decorator可以提供比繼承更多的靈活性。 2. 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合。(這一條更能體現) 5.缺點 1. 這種比繼承更加靈活機動的特性,也同時意味著更加多的復雜性。 2. 裝飾模式會導致設計中出現許多小類,如果過度使用,會使程序變得很復雜。 3. 裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇 6.設計原則 1. 多用組合,少用繼承。 利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。然而,如果能夠利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。 2. 類應設計的對擴展開放,對修改關閉。 8.模式簡化(最後會給出2種寫法僅供參考) 1. 如果只有一個Concrete Component類而沒有抽象的Component接口時,可以讓Decorator繼承Concrete Component。 2. 如果只有一個Concrete Decorator類時,可以將Decorator和Concrete Decorator合並。 9.代碼示例 (1)抽象接口 復制代碼 /// <summary> /// 定義Component對象接口 /// </summary> public abstract class Component { public abstract void Operation();//一個抽象的職責 } /// <summary> /// 具體對象 /// </summary> class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("具體對象的操作"); } } //裝飾者抽象類 abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } class ConcreteDecoratorA : Decorator { public override void Operation() { base.Operation(); //首先運行原Compnent的Operation(),再執行本類的功能,如AddedBehavior,相當於對原Component進行了裝飾 Console.WriteLine("具體裝飾對象A的操作"); } } class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); //首先運行原Compnent的Operation(),再執行本類的功能,如AddedBehavior,相當於對原Component進行了裝飾 Console.WriteLine("具體裝飾對象B的操作"); } } 復制代碼 (2)無抽象接口 復制代碼 public class Car { public virtual void Description() { Console.Write("基本"); } } public class ESPDecorator : Car { Car car; public ESPDecorator(Car car) { this.car = car; } public override void Description() { car.Description(); Console.WriteLine("帶有ESP功能"); } } public class OtherDecorator : Car { Car car; public OtherDecorator(Car car) { this.car = car; } public override void Description() { car.Description(); Console.WriteLine("帶有其它功能"); } } //第一種 ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); d1.SetComponent(c); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d2.SetComponent(c); d2.Operation(); //第二種 Car car = new ESPDecorator(new OtherDecorator(new Car())); car.Description();