裝飾模式,英文名稱:Decorator Pattern
。我第一次看到這個名稱想到的是另外一個詞語「裝修」,我就說說我對「裝修」的理解吧,大家一定要看清楚,是「裝修」,不是「裝飾」。在房子裝修的過程中,各種功能可以相互組合,來增加房子的功用。類似的,如果我們在軟體系統中,要給某個型別或者物件增加功能,如果使用「繼承」的方案來寫程式碼,就會出現子類暴漲的情況。比如:IMarbleStyle是大理石風格的一個功能,IKeepWarm是保溫的一個介面定義,IHouseSecurity是房子安全的一個介面,就三個介面來說,House是我們房子,我們的房子要什麼功能就實現什麼介面,如果房子要的是複合功能,介面不同的組合就有不同的結果,這樣就導致我們子類膨脹嚴重,如果需要在增加功能,子類會成指數增長。
上述的問題的根源在於我們「過度地使用了繼承來擴充套件物件的功能」,由於繼承為型別引入的靜態特質,所謂靜態特質,就是說如果想要某種功能,我們必須在編譯的時候就要定義這個類,這也是強型別語言的特點。靜態,就是指在編譯的時候要確定的東西;動態,是指執行時確定的東西。使得這種擴充套件方式缺乏靈活性;並且隨著子類的增多(擴充套件功能的增多),各種子類的組合(擴充套件功能的組合)會導致更多子類的膨脹(多繼承)。如何使「物件功能的擴充套件」能夠根據需要來動態(即執行時)地實現?同時避免「擴充套件功能的增多」帶來的子類膨脹問題?從而使得任何「功能擴充套件變化」所導致的影響降為最低?裝飾者模式解決此問題應運而生,動態地給一個物件增加一些額外的職責。
抽象構件角色(Component):給出一個抽象介面,以規範準備接收附加責任的物件。
具體構件角色(Concrete Component):定義一個將要接收附加責任的類。
裝飾角色(Decorator):持有一個構件(Component)物件的範例,並實現一個與抽象構件介面一致的介面。
具體裝飾角色(Concrete Decorator):負責給構件物件新增上附加的責任。
以裝修房子為例,完成裝飾著模式的程式碼實現
/// <summary>
/// 該抽象類就是房子抽象介面的定義,該型別就相當於是Component型別,是餃子餡,需要裝飾的,需要包裝的
/// </summary>
public abstract class House
{
/// <summary>
/// 房子的裝修方法--該操作相當於Component型別的Operation方法
/// </summary>
public abstract void Renovation();
}
/// <summary>
/// MyHouse的房子,我要按我的要求做房子,相當於ConcreteComponent型別
/// </summary>
public sealed class MyHouse : House
{
public override void Renovation()
{
Console.WriteLine("裝修我的房子");
}
}
/// <summary>
/// 該抽象類就是裝飾介面的定義,該型別就相當於是Decorator型別,如果需要具體的功能,可以子類化該型別
/// </summary>
public abstract class DecorationStrategy : House //關鍵點之二,體現關係為Is-a,有了這個關係,裝飾的類也可以繼續裝飾了
{
//通過組合方式參照Decorator型別,該型別實施具體功能的增加
//這是關鍵點之一,包含關係,體現為Has-a
protected House _house;
//通過構造器注入,初始化平臺實現
protected DecorationStrategy(House house)
{
this._house = house;
}
//該方法就相當於Decorator型別的Operation方法
public override void Renovation()
{
if (this._house != null)
{
this._house.Renovation();
}
}
}
/// <summary>
/// 具有安全功能的裝置,可以提供監視和報警功能,相當於ConcreteDecoratorA型別
/// </summary>
public sealed class HouseSecurityDecorator : DecorationStrategy
{
public HouseSecurityDecorator(House house) : base(house) { }
public override void Renovation()
{
base.Renovation();
Console.WriteLine("增加安全系統");
}
}
/// <summary>
/// 具有保溫介面的材料,提供保溫功能,相當於ConcreteDecoratorB型別
/// </summary>
public sealed class KeepWarmDecorator : DecorationStrategy
{
public KeepWarmDecorator(House house) : base(house) { }
public override void Renovation()
{
base.Renovation();
Console.WriteLine("增加保溫的功能");
}
}
public void RunTest()
{
//這就是我們需要裝飾的房子
House myselfHouse = new MyHouse();
DecorationStrategy securityHouse = new HouseSecurityDecorator(myselfHouse);
securityHouse.Renovation();
/*
* 此時房子就有了安全系統了.....
*/
//【1】如果我既要安全系統又要保暖呢,繼續裝飾就行
//DecorationStrategy securityAndWarmHouse = new KeepWarmDecorator(myselfHouse);
//securityAndWarmHouse.Renovation();
Console.WriteLine("\r\n*****************************\r\n");
//【2】如果我既要安全系統又要保暖呢,繼續裝飾就行【和上邊的進行執行比對】
//【對執行結果難理解的話,打斷點單步執行進行理解】
DecorationStrategy securityAndWarmHouse1 = new KeepWarmDecorator(securityHouse);
securityAndWarmHouse1.Renovation();
}
把抽象介面與其實現解耦。
抽象和實現可以獨立擴充套件,不會影響到對方。
實現細節對客戶透明,對使用者隱藏了具體實現細節。
本文來自部落格園,作者:碼農阿亮,轉載請註明原文連結:https://www.cnblogs.com/wml-it/p/17693849.html