裝飾者模式
參考《head first 設計模式》
裝飾者模式像包了一層層糖紙的糖果,每一層糖紙都繼承自同一個基類。遵循開閉設計原則,即對擴展開放,對修改關閉。就是寫好的代碼能不改就不要改,改了可能要加班加點了。這個模式像那種二道販子,把別人做好的東西做個包裝,添加點自己的東西再拿出去賣。
定義:動態的將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更富有彈性的替代方案。
特徵:
- 裝飾者和被裝飾者具有相同的基類;
- 可以用一個或多個裝飾者包裝一個對象;
- 既然裝飾者和被裝飾者具有相同的基類,可以用裝飾者替代被裝飾者;
- 裝飾者可以在被裝飾者的行爲前或後,添加自己的行爲;
- 對象可以在任何時候被裝飾。
心得
裝飾者和被裝飾者必須要繼承自同一個基類的目的是,在裝飾者的內部有基類型字段用來保存被裝飾者,一個裝飾者被再次裝飾後,它對於後者而言就成了被裝飾者,如果不是繼承自同一個基類,它就不能保存到後者的基類型字段裏了,從而無法再次被擴展。
## 結構
## 示例代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 裝飾者模式
{
class Program
{
static void Main(string[] args)
{
Beverage beverage=new Espresso(); // 一杯濃咖啡,不加調料
Console.WriteLine($"{beverage.GetDescription()} ${beverage.Cost()}");
Beverage beverage2=new DarkRoast(); // 一杯深焙咖啡
beverage2=new Mocha(beverage2); // 添加摩卡
beverage2 = new Mocha(beverage2); // 添加摩卡
beverage2 = new Whip(beverage2); // 添加奶泡
Console.WriteLine($"{beverage2.GetDescription()} ${beverage2.Cost()}");
Beverage beverage3=new HouseBlend(); // 一杯混合咖啡
beverage3=new Soy(beverage3); // 添加豆漿
beverage3=new Mocha(beverage3); // 添加摩卡
beverage3=new Whip(beverage3); // 添加奶泡
Console.WriteLine($"{beverage3.GetDescription()} ${beverage3.Cost()}");
Console.ReadKey();
}
}
#region 計算咖啡飲料的價格
// 咖啡飲料中可能加入不同的飲料,價格也可能會發生改變
// 飲料抽象類,一般裝飾者模式用抽象類,也可以用接口
public abstract class Beverage
{
public string Description = "Unknown Beverage";
public virtual string GetDescription()
{
return Description;
}
// 計算飲料價格
public abstract double Cost();
}
// 調料裝飾者抽象類,給所有具體的調料類繼承
public abstract class CondimentDecorator : Beverage
{
// 覆蓋基類中的獲取描述的方法
public override string GetDescription()
{
return string.Empty;
}
}
#region 被裝飾者組件
// 特濃咖啡類
public class Espresso : Beverage
{
public Espresso()
{
Description = "Espresso";
}
public override double Cost()
{
return 1.99;
}
}
// 混合咖啡類
public class HouseBlend : Beverage
{
public HouseBlend()
{
Description = "HouseBlend";
}
public override double Cost()
{
return 0.89;
}
}
// 深焙咖啡類
public class DarkRoast : Beverage
{
public DarkRoast()
{
Description = "DarkRoast";
}
public override double Cost()
{
return 0.99;
}
}
// 低咖啡因咖啡類
public class Decaf : Beverage
{
public Decaf()
{
Description = "Decaf";
}
public override double Cost()
{
return 1.05;
}
}
#endregion
#region 裝飾者
// 各種咖啡配料
// 摩卡
public class Mocha : CondimentDecorator
{
private readonly Beverage _beverage; // 保存被裝飾者
public Mocha(Beverage beverage)
{
_beverage = beverage;
}
public override string GetDescription()
{
return _beverage.GetDescription() + ", Mocha";
}
public override double Cost()
{
return .20 + _beverage.Cost();
}
}
// 牛奶
public class Milk : CondimentDecorator
{
private readonly Beverage _beverage; // 保存被裝飾者
public Milk(Beverage beverage)
{
_beverage = beverage;
}
public override string GetDescription()
{
return _beverage.GetDescription() + ", Milk";
}
public override double Cost()
{
return .10 + _beverage.Cost();
}
}
// 豆漿
public class Soy : CondimentDecorator
{
private readonly Beverage _beverage; // 保存被裝飾者
public Soy(Beverage beverage)
{
_beverage = beverage;
}
public override string GetDescription()
{
return _beverage.GetDescription() + ", Soy";
}
public override double Cost()
{
return .15 + _beverage.Cost();
}
}
// 奶泡
public class Whip : CondimentDecorator
{
private readonly Beverage _beverage; // 保存被裝飾者
public Whip(Beverage beverage)
{
_beverage = beverage;
}
public override string GetDescription()
{
return _beverage.GetDescription() + ", Whip";
}
public override double Cost()
{
return .10 + _beverage.Cost();
}
}
#endregion
#endregion
}