Decorator裝飾者模式:
裝飾者模式通常用來動態的添加物件的前後新功能或行為,不需要時也方便移除該功能,而不需要修改原始類別的程式碼,允許你將功能封裝於獨立的類別中,組合這些裝飾者而實現功能。
透過裝飾者模式也符合開放封閉原則,對擴充是開放的,對修改是封閉的。
用裝飾者點飲料
點一杯飲料可能需要加許多料,可能有很多種不同的情境及價錢的計算。
假設一杯"基本飲料款"(被裝飾者),需要加入草莓、巧克力、半糖,可以用裝飾者模式實現,那假如今天有另一杯飲料的款式,也可以通過加入草莓、巧克力、半糖裝飾者加入,而不用修改現有的程式。
internal class Program
{
static void Main(string[] args)
{
//基本飲料
BasicDrink basicDrink = new BasicDrink();
Console.WriteLine(basicDrink.AddCost() + "元");
Console.WriteLine(basicDrink.AddMaterial());
//加入草莓
IDrink strawberryDrink = new StrawberryDecorator(basicDrink);
Console.WriteLine(strawberryDrink.AddCost() + "元");
Console.WriteLine(strawberryDrink.AddMaterial());
//加入巧克力
IDrink chocolateDrink = new ChocolateDecorator(strawberryDrink);
Console.WriteLine(chocolateDrink.AddCost() + "元");
Console.WriteLine(chocolateDrink.AddMaterial());
//加入半糖
IDrink halfSugarDrink = new HalfSugarDecorator(chocolateDrink);
Console.WriteLine(halfSugarDrink.AddCost() + "元");
Console.WriteLine(halfSugarDrink.AddMaterial());
Console.ReadLine();
}
}
/// <summary>
/// 飲料介面
/// </summary>
public interface IDrink
{
string AddMaterial(); //加入飲料材料
double AddCost(); //加入金額
}
/// <summary>
/// 基本飲料類別(可定義不同飲料基底)
/// </summary>
public class BasicDrink : IDrink
{
public double AddCost()
{
return 10;
}
public string AddMaterial()
{
return "基本飲料款";
}
}
/// <summary>
/// 飲料裝飾者
/// </summary>
public abstract class DrinkDecorator : IDrink
{
protected IDrink drink; //被裝飾的實體
public DrinkDecorator(IDrink drink)
{
this.drink = drink;
}
public virtual double AddCost()
{
return drink.AddCost();
}
public virtual string AddMaterial()
{
return drink.AddMaterial();
}
}
/// <summary>
/// 草莓裝飾者
/// </summary>
public class StrawberryDecorator : DrinkDecorator
{
public StrawberryDecorator(IDrink drink) : base(drink)
{
}
public override double AddCost()
{
return base.AddCost() + 15;
}
public override string AddMaterial()
{
return base.AddMaterial() + " + 草莓";
}
}
/// <summary>
/// 巧克力裝飾者
/// </summary>
public class ChocolateDecorator : DrinkDecorator
{
public ChocolateDecorator(IDrink drink) : base(drink)
{
}
public override double AddCost()
{
return base.AddCost() + 20;
}
public override string AddMaterial()
{
return base.AddMaterial() + " + 巧克力";
}
}
/// <summary>
/// 半糖裝飾者
/// </summary>
public class HalfSugarDecorator : DrinkDecorator
{
public HalfSugarDecorator(IDrink drink) : base(drink)
{
}
public override double AddCost()
{
return base.AddCost(); //糖不用加錢,也可以不寫此方法override
}
public override string AddMaterial()
{
return base.AddMaterial() + " + 半糖";
}
}
裝飾者也很適合用來執行有順序的行為
例如吃檔後需對一個Table的操作,行為模式可能是:
刪除所有資料在全部新增,又或者只刪除吃檔沒有存在於Table資料,在新增及更新重複的資料。
internal class Program
{
static void Main(string[] args)
{
#region 全部刪除,在新增資料
IDBAction txtFile = new TxtFileProcess(); //讀取Txt檔案程序
IDBAction truncateTable = new TruncateTable(txtFile); //刪除所有資料
IDBAction insertTable = new InsertTable(truncateTable); //新增資料
IDBAction countTableRecords = new CountTableRecords(insertTable); //計算筆數
#endregion
#region 刪除吃檔不存在的資料,在新增或更新重複資料
//IDBAction txtFile = new TxtFileProcess(); //讀取Txt檔案程序
//IDBAction deleteTable = new DeleteTable(txtFile); //刪除吃檔不存在的資料
//IDBAction insertOrUpdateTable = new InsertOrUpdateTable(deleteTable); //新增或更新重複資料
//IDBAction countTableRecords = new CountTableRecords(insertOrUpdateTable); //計算筆數
#endregion
countTableRecords.Execute(); //執行
Console.ReadLine();
}
}
/// <summary>
/// DB執行介面
/// </summary>
public interface IDBAction
{
void Execute();
}
/// <summary>
/// DB裝飾者
/// </summary>
public abstract class DBActionDecorator : IDBAction
{
protected IDBAction action;
public DBActionDecorator(IDBAction dBAction)
{
this.action = dBAction;
}
public virtual void Execute()
{
if (this.action != null)
this.action.Execute();
}
}
/// <summary>
/// Txt讀檔處理程序
/// </summary>
public class TxtFileProcess : IDBAction
{
public void Execute()
{
Console.WriteLine("讀取檔案");
}
}
/// <summary>
/// 刪除所有資料
/// </summary>
public class TruncateTable : DBActionDecorator
{
public TruncateTable(IDBAction dBAction) : base(dBAction)
{
}
public override void Execute()
{
base.Execute();
Console.WriteLine("刪除所有資料");
}
}
/// <summary>
/// 刪除吃檔不存在的資料
/// </summary>
public class DeleteTable : DBActionDecorator
{
public DeleteTable(IDBAction dBAction) : base(dBAction)
{
}
public override void Execute()
{
base.Execute();
Console.WriteLine("刪除吃檔沒有資料");
}
}
/// <summary>
/// 新增資料
/// </summary>
public class InsertTable : DBActionDecorator
{
public InsertTable(IDBAction dBAction) : base(dBAction)
{
}
public override void Execute()
{
base.Execute();
Console.WriteLine("新增資料");
}
}
/// <summary>
/// 新增或更新重複資料
/// </summary>
public class InsertOrUpdateTable : DBActionDecorator
{
public InsertOrUpdateTable(IDBAction dBAction) : base(dBAction)
{
}
public override void Execute()
{
base.Execute();
Console.WriteLine("新增或更新重複的資料");
}
}
/// <summary>
/// 計算筆數
/// </summary>
public class CountTableRecords : DBActionDecorator
{
public CountTableRecords(IDBAction dBAction) : base(dBAction)
{
}
public override void Execute()
{
base.Execute();
Console.WriteLine("計算筆數");
}
}
全部刪除,在新增資料
刪除吃檔不存在的資料,在新增或更新重複資料