1、裝飾(Decorator)模式
動態給一個對象添加一些額外的職責。就增加功能來說,裝飾模式比生成子類更為靈活。
Component是定義一個對象接口、可以給這些對象動態地添加職責。ConcreteComponent是定義了一個具體的對象,也可以給這個對象添加一些職責。Decorator,裝飾抽象類,繼承了Component,從外類來擴展Component類的功能,但對於Component來說,是無需知道Decorator的存在的。至於ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。
2、結構圖
Component 類:
abstract class Component
{
public abstract void Operation();
}
ConcreteComponent類:
class ConcreteComponent : Component
{
public voerride void Operation()
{
Console.WriteLine("具體對象的操作");
}
}
Decorator類:
abstract class Decorator:Component
{
protected Component component;
public void SetComponent(Component component)//設置Component
{
this.component = component;
}
public voerride void Operation()
{
if(component != null)
{
component.Operation();
}
}
}
ConcreteDecoratorA 類:
class ConcreteDecoratorA : Decorator
{
private string addedState;//本類的獨有功能,以區別於ConcreteDecoratorB
public voerride void Operation()
{
base.Operation();
addedState = "New State";
Console.WriteLine("具體裝飾對象A的操作");
}
}
ConcreteDecoratorB 類:
class ConcreteDecoratorB : Decorator
{
private string addedState;//本類的獨有功能,以區別於ConcreteDecoratorB
public voerride void Operation()
{
base.Operation();//首先運行原Component的Operation(),再執行本類的功能,如AddedBehavior(),相當於對原Component進行了裝飾
addedBehavior();
Console.WriteLine("具體裝飾對象B的操作");
}
private void addedBehavior()//本類獨有的方法以區別於ConcreteDecoratorA
{
}
}
客戶端代碼:
static void Main(string[] args)
{
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA da = new ConcreteDecoratorA();
ConcreteDecoratorB db = new ConcreteDecoratorB();
da.SetComponent(c);
db.SetComponent(da);
db.Operation();
Console.Read();
}
裝飾模式是利用SetCompnent來對對象進行包裝的,這樣每個裝飾對象的實現就和如何使用這個對象分離開了,每個裝飾對象只關心自己的功能,不需要關心如何被添加到對象鏈當中。
如果只有一個ConcreteComponent類而沒有抽象的Component類,那么Decorator類可以是ConcreteComponent的一個子類。同樣道理,如果只有一個ConcreteDecorator類,那么就沒必要建立一個單獨的Decorator類,而可以把Decorator和ConcreteDecorator的責任合並成一個類。
3、總結
裝飾模式是為已有功能動態地添加更多功能的一種方式。當系統需要新功能的時候,是向舊的類中添加新的代碼。這些新添加的代碼通常裝飾了原有類的核心職責或主要行為,他們在主類中加入了新的字段,新的方法和新的邏輯,從而增加了主類的復雜度,這些新加入的東西僅僅是為了滿足一些只在某種特定情況下才會執行的特殊行為需要。而裝飾模式卻提供了一個非常好的解決方案,它把每個要裝飾的功放在一個單獨的類中,並讓這個類包裝它所要裝飾的對象,因此,當需要執行特殊行為時,客戶代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象。
裝飾模式優點是把類中的裝飾功能從類中搬移去除,這樣可以簡化原有的類,有效地把類的核心職責和裝飾功能區分開了,而且可以去除相關類中重復的裝飾邏輯。