設計模式學習(三): 裝飾者模式 (附C#實現)
阿新 • • 發佈:2017-10-04
ring oid decorator 所有 clas blog mage return .cn
需求
做一個咖啡店的訂單系統。
買咖啡時,可以要求加入各種調料,如奶,豆漿,摩卡等。咖啡店會根據調料的不同收取不同的費用。訂單系統要考慮這些。
初版設計
然後下面就是所有的咖啡....:
cost方法將計算出咖啡加上各種調料後的價格。
這種方法太笨了。。。必須換一種。
再版設計
使用實例變量和繼承!
但是有新的問題:
1.調料價格變化就需要更改現有的代碼。
2.一旦出現新的調料,就需要加上新的方法,並改變超類中的cost方法。
3.如果有新的飲料,有些調料可能會不適用。
4.想買雙倍的摩卡咖啡怎麽辦?
設計原則
類應該對擴展開發,對修改關閉。
使用裝飾者模式
裝飾者模式定義
裝飾者模式動態的將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
重新設計
C#代碼實現
Beverage:
namespace C03DecoratorPattern.Bases { public abstract class Beverage { protected string Description; protected Beverage() { Description = "Unknown Beverage"; } public abstract double Cost(); public virtualstring GetDescription() { return Description; } } }
CondimentDecorator:
namespace C03DecoratorPattern.Bases { public abstract class CondimentDecorator : Beverage { public abstract override double Cost(); public abstract override string GetDescription(); } }
咖啡們:
namespace C03DecoratorPattern.Beverages { public class Espresso : Beverage { public Espresso() { Description = "Espresso"; } public override double Cost() { return 1.99; } } } namespace C03DecoratorPattern.Beverages { public class HouseBlend : Beverage { public HouseBlend() { Description = "House Blend Coffee"; } public override double Cost() { return .89; } } }
調料們:
namespace C03DecoratorPattern.Condiments { public class Milk : CondimentDecorator { private readonly Beverage _beverage; public Milk(Beverage beverage) { _beverage = beverage; } public override double Cost() { return .34 + _beverage.Cost(); } public override string GetDescription() { return $"{_beverage.GetDescription()}, Milk"; } } } namespace C03DecoratorPattern.Condiments { public class Mocha : CondimentDecorator { private readonly Beverage _beverage; public Mocha(Beverage beverage) { _beverage = beverage; } public override double Cost() { return .2 + _beverage.Cost(); } public override string GetDescription() { return $"{_beverage.GetDescription()}, Mocha"; } } } namespace C03DecoratorPattern.Condiments { public class Soy: CondimentDecorator { private readonly Beverage _beverage; public Soy(Beverage beverage) { _beverage = beverage; } public override double Cost() { return .17 + _beverage.Cost(); } public override string GetDescription() { return $"{_beverage.GetDescription()}, Soy"; } } }
測試程序:
namespace C03DecoratorPattern { class Program { static void Main(string[] args) { Beverage beverage = new Espresso(); Console.WriteLine($"{beverage.GetDescription()} $ {beverage.Cost()}"); Beverage beverage2 = new HouseBlend(); beverage2 = new Mocha(beverage2); beverage2 = new Milk(beverage2); beverage2 = new Soy(beverage2); Console.WriteLine($"{beverage2.GetDescription()} $ {beverage2.Cost()}"); Console.ReadLine(); } } }
運行結果:
設計模式學習(三): 裝飾者模式 (附C#實現)