如果要對一個特定類別擴充新的功能,在不修改原始類別的前題下,通常我們會選擇使用繼承方式來建立一個新的類別。 例如一個類別叫做漢堡,價格 20 ,若是要製做漢堡蛋,就可以繼承漢堡,然後變更售價的屬性。 但這樣子的做法,若有多種添加副食,且允許使用者做任意選擇組合,就會變的相當難以維護。 另外一種方式就是透過裝飾者模式(Decorate Pattern)來處理,它比繼承方法的優勢就在於彈性,而且符合「開放-封閉原則」(Open/Closed Principle, OCP)的程式架構。
//主食(被裝飾者)
public abstract class Breakfast
{
protected string description;
public abstract string Description();
public abstract int Cost();
}
//主食1
public class Toast : Breakfast
{
public override string Description()
{
return "土司";
}
public override int Cost()
{
return 15;
}
}
//主食2
public class FanTuan : Breakfast
{
public override string Description()
{
return "飯團";
}
public override int Cost()
{
return 25;
}
}
//配料(裝飾者) 裝飾者類別必須繼承自被裝飾者,且亦為抽象類別
public abstract class SubFoodDecorator : Breakfast
{
//有必要做異動的功能, 必須設定為 abstract override , 以便在子類別中重新實作
public abstract override string Description();
public abstract override int Cost();
}
public class Cheese : SubFoodDecorator //起司是一個裝飾者,所以繼承自抽象的裝飾者類別
{
private Breakfast _breadfast;
public Cheese(Breakfast b)
{
_breadfast = b;
}
public override string Description()
{
return "起士" + _breadfast.Description();
}
public override int Cost()
{
return 10 + _breadfast.Cost();
}
}
public class Pork : SubFoodDecorator //起司是一個裝飾者,所以繼承自抽象的裝飾者類別
{
private Breakfast _breadfast;
public Pork(Breakfast b)
{
_breadfast = b;
}
public override string Description()
{
return "肉片" + _breadfast.Description();
}
public override int Cost()
{
return 30 + _breadfast.Cost();
}
}
public class Egg : SubFoodDecorator //火腿是一個裝飾者,所以繼承自抽象的裝飾者類別
{
Breakfast _breadfast;
public Egg(Breakfast b)
{
_breadfast = b;
}
public override string Description()
{
return "蛋" + _breadfast.Description();
}
public override int Cost()
{
return 5 + _breadfast.Cost();
}
}
使用時,就可以參考以下範例,這個方法的好處是,若有新增加的主食或副食,只要新增該項類別,無須調整其他的程式碼。 它的擴增功能是動態加入的,而非事先定義在該類別中。
Breakfast breadfast1 = new FanTuan();
breadfast1 = new Egg(breadfast1);
Console.WriteLine("{0} {1}元", breadfast1.Description(), breadfast1.Cost());
//蛋飯團 30元。
Breakfast breadfast2 = new Toast();
breadfast2 = new Pork(breadfast2);
breadfast2 = new Egg(breadfast2);
breadfast2 = new Cheese(breadfast2);
Console.WriteLine("{0} {1}元", breadfast2.Description(), breadfast2.Cost());
//起士蛋肉片土司 60元

沒有留言:
張貼留言