一、定義
動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更爲靈活。
二、結構圖
裝飾模式就是利用SetComponent來對對象進行包裝的。這樣每個裝飾對象的實現就和如何使用這個對象分離開了,每個裝飾對象只關心自己的功能,不需要關心如何被添加到對象鏈當中。
三、實例
如果只有一個ConcreteComponent類而沒有抽象的Component類,那麼Decorator類可以是ConcreteComponent的一個子類。同樣道理,如果只有一個ConcreteDecorator類,那麼就沒有必要建立一個單獨的Decorator類,而可以把Decorator和ConcreteDecorator的責任合併成一個類。
如下實例屬於上述第一種情況:
Person類(ConcreteComponent)
public class Person
{
public Person( )
{
}
private string name;
public Person( string name )
{
this.name = name;
}
public virtual void Show( )
{
Console.WriteLine( "裝扮的{0}", name );
}
}
服飾類(Decorator)
class Finery : Person
{
protected Person component;
//關鍵點:利用Decorate (SetComponent)來對對象進行包裝
public void Decorate( Person component )
{
this.component = component;
}
public override void Show()
{
if( component != null )
{
component.Show( );
}
}
}
具體服飾類(ConcreteDecorator)
class BigTrouser : Finery
{
public override void Show( )
{
Console.Write( "垮褲 " );
base.Show( );
}
}
class Sneaker : Finery
{
public override void Show( )
{
Console.Write( "破球鞋 " );
base.Show( );
}
}
class TShits : Finery
{
public override void Show( )
{
Console.Write( "T-Shit " );
base.Show( );
}
}
調用:
static void Main( string[ ] args )
{
Person andy = new Person( "andy" );
Sneaker sneaker = new Sneaker( );
BigTrouser bigtrouser = new BigTrouser( );
TShits tshit = new TShits( );
sneaker.Decorate( andy );
bigtrouser.Decorate( sneaker );
tshit.Decorate( bigtrouser );
tshit.Show( );
Console.Read( );
}
運行結果:
四、總結
裝飾模式是爲已有功能動態地添加更多功能的一種方式。
優點:
- 裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活
- 通過使用不同的具體裝飾類以及這些類的排列組合,設計師可以創造出很多不同行爲的組合
- 裝飾者模式有很好地可擴展性
缺點:
裝飾者模式會導致設計中出現許多小對象,如果過度使用,會讓程序變的更復雜。並且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。
五、使用場景
下面讓我們看看裝飾者模式具體在哪些情況下使用,在以下情況下應當使用裝飾者模式:
- 需要擴展一個類的功能或給一個類增加附加責任。
- 需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。
- 需要增加由一些基本功能的排列組合而產生的非常大量的功能