裝飾器模式介紹

裝飾器的核心就是再不改原有類的基礎上給類新增功能,可以避免繼承導致的子類過多,可避免AOP帶來的復雜性,
裝飾器主要解決的時直接繼承下因功能的不斷橫向擴展導致子類膨脹的問題,而是用裝飾器模式后就會比直接繼承顯得更加靈活同時這樣也就不再需要考慮子類的維護,
在實作的程序中,具體實作只關心擴展部分的功能,同時不會影響原有類的核心服務,也不會因為使用繼承方式而導致的多余子類,增加了整體的靈活性,
裝飾器模式滿足單一職責原則,可以在自己的裝飾類中完成功能邏輯的擴展,而不影響主類,同時可以按需在運行時添加和洗掉這部分邏輯,另外裝飾器模式與繼承父類重寫方法,在某些時候需要按需選擇,并不一定某一個就是最好,
裝飾器實作的重點是對抽象類繼承介面方法的使用,同時設定被繼承的介面可以通過建構式傳遞其實作類,由此增加擴展性并重寫方法里可以實作此部分父類實作的功能,
封裝器是一個能與其他目標物件連接的物件,封裝器包含與目標物件相同的一系列方法,它會將所有接收到的請求委派給目標物件,但是封裝器可以在將請求委派給目標前后對其進行處理,所以可能會改變最終結果,
裝飾模式由于目標物件和裝飾器遵循同一介面,因此你可用裝飾來對物件進行無限次的封裝,結果物件將獲得所有封裝器疊加而來的行為,
裝飾器模式的抽象點
-
抽象構件角色-定義抽象介面
-
具體構件角色-實作抽象介面,可以是一組
-
裝飾角色-定義抽象類并繼承介面中的方法,保證一致性
-
具體裝飾角色-擴展裝飾具體的實作邏輯
繼承可能引發的幾個嚴重問題:
1、繼承是靜態的,你無法在運行時更改已有物件的行為,只能使用由不同子類創建的物件來替代當前的整個物件,
2、子類只能有一個父類,大部分編程語言不支持多繼承,
裝飾器結構
- 部件 宣告封裝器和被封裝物件的公用介面,
- 具體部件 類是被封裝物件所屬的類,它定義了基礎行為,但裝飾類可以改變這些行為,
- 基礎裝飾 類擁有一個指向被封裝物件的參考成員變數,該變數的型別應當被宣告為通用部件介面,這樣它就可以參考具體的部件和裝飾,裝飾基類會將所有操作委派給被封裝的物件,
- 具體裝飾類 定義了可動態添加到部件的額外行為,具體裝飾類會重寫裝飾基類的方法,并在呼叫父類方法之前或之后進行額外的行為,
- 客戶端 可以使用多層裝飾來封裝部件,只要它能使用通用介面與所有物件互動即可,
適用場景
1、在無需修改代碼的情況下即可使用物件,且希望在運行時為物件新增額外的行為,可以使用裝飾模式,
裝飾能將業務邏輯組織為層次結構,你可為各層創建一個裝飾,在運行時將各種不同邏輯組成物件,由于這些物件都遵循通用介面,客戶端代碼能以相同的方式使用這些物件,
2、當某些業務無法使用繼承來擴展物件行為時,可以使用裝飾模式,
裝飾器模式優缺點
優點:
-
你需要創建新子類即可擴展物件的行為,
-
可在運行時添加或洗掉物件的功能,
-
可以用多個裝飾封裝物件來組合幾種行為,
-
滿足單一職責原則,
缺點:
-
在封裝器堆疊中洗掉特定封裝器比較困難
-
實作行為不受裝飾堆疊順序影響的裝飾比較困難
-
剛開始各層的初始化配置代碼比較糟糕
Demo
/// <summary>
/// 組件
/// </summary>
public abstract class Component
{
public abstract string Operation();
}
}
/// <summary>
/// 抽象的裝飾者
/// </summary>
class ConcreteComponent:Component
{
public override string Operation()
{
return "ConcreteComponent";
}
}
abstract class Decorator:Component
{
protected Component _component;
public Decorator(Component component)
{
this._component = component;
}
public void SetComponent(Component component)
{
this._component = component;
}
public override string Operation()
{
if (this._component!=null)
{
return this._component.Operation();
}
else
{
return string.Empty;
}
}
}
class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(Component comp):base(comp)
{
}
public override string Operation()
{
return "ConcreteDecoratorA " + base.Operation();
}
}
class ConcreteDecoratorB:Decorator
{
public ConcreteDecoratorB(Component comp)
: base(comp)
{
}
public override string Operation()
{
return "ConcreteDecoratorA " + base.Operation();
}
}
public class Client
{
public void ClientCode(Component component)
{
Console.WriteLine("Result:"+component.Operation());
}
}
class Program
{
static void Main(string[] args)
{
Client client = new Client();
var temp = new ConcreteComponent();
Console.WriteLine("Start------");
Console.WriteLine();
ConcreteDecoratorA d1 = new ConcreteDecoratorA(temp);
ConcreteDecoratorB d2 = new ConcreteDecoratorB(d1);
Console.WriteLine("Start Music");
client.ClientCode(d2);
Console.ReadKey();
}
}

其實可以看出裝飾器模式和組合模式還是有異曲同工之處的,裝飾器模式是對既有類中方法的可重寫,也就是可以改變其方法的結構,而組合則是不能改變其既有類中的方法,只能將其組合成想要實作的樣子,
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的,
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/294098.html
標籤:.NET技术
上一篇:設計模式之組合
