前言:
策略模式可以定義一系列的算法,並且根據需求選擇算法。算法之間還可以相互替換,不影響客戶端的使用。
需求:
還是以商場的收銀系統爲例,這次添加一個需求。在上一個需求上加一個,打5折和打7折的需求。
類圖:
實現:
抽象策略類(沒有具體的實現策略,而是把具體策略的共同方法抽象到裏面)
/// <summary>
/// 現金收費的抽象類,父類。
/// </summary>
abstract class CashSuper
{
/// <summary>
/// 現金收費的抽象方法
/// </summary>
/// <param name="money">原價</param>
/// <returns>當前價格</returns>
public abstract double acceptCash(double money);
}//end CashSuper
正常收費策略(繼承抽象策略類)
/// <summary>
/// 正常收費子類
/// </summary>
class CashNormal : CashSuper
{
/// <summary>
/// 重寫父類的收費方法
/// </summary>
/// <param name="money">原價</param>
/// <returns>當前價格</returns>
public override double acceptCash(double money)
{
return money;//原價返回
}//end acceptCash
}//end CashNormal
打折策略(繼承抽象策略類)
/// <summary>
/// 打折收費子類
/// </summary>
class CashRedbate : CashSuper
{
private double moneyRebate = 1d;//具體打幾折
/// <summary>
/// 獲取具體打幾折
/// </summary>
/// <param name="moneyRebate">具體打幾折</param>
public CashRedbate(string moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
}//end CashRedbate
/// <summary>
///打折的方法
/// </summary>
/// <param name="money">原價</param>
/// <returns>打折之後的價格</returns>
public override double acceptCash(double money)
{
//原價*具體打折數=打折之後的價格
return money * moneyRebate;
}//end aceptCash
}//end CashRedbate
返利策略(繼承抽象策略類)
/// <summary>
/// 返利收費子類
/// </summary>
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;//返利條件
private double moneyReturn = 0.0d;//反多少
/// <summary>
/// 返利條件初始化
/// </summary>
/// <param name="moneyCondition">返利條件</param>
/// <param name="moneyReturn">反多少</param>
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);//返利條件
this.moneyReturn = double.Parse(moneyReturn);//反多少
}//end CashRetur
/// <summary>
/// 返利計算方法
/// </summary>
/// <param name="money">原價</param>
/// <returns>返利之後的價格</returns>
public override double acceptCash(double money)
{
double result = money;//要返回的價格
//判斷是否滿足返利的要求
if (money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}//end if
return result;//返回價格
}//end AcceptCash
}//end CashReturn
客戶端(在客戶端用switch選擇具體的策略,把選好的具體策略傳入CashFactoury裏面。然後根據傳進去的策略進行具體的計算。)
double total = 0.0d;
private void butok_Click(object sender, EventArgs e)
{
CashContext cc = null;//實例化策略模式
//根據條件選擇策略
switch (cbxType.Selecteditem.Tostring())
{
case "正常收費":
cc = new CashNormal();
break;
case "滿300返100":
cc = new CashReturn("300", "100");
break;
case "打8折":
cc = new CashRedbate("0.8");
break;
case "打5折":
cc = new CashRedbate("0.5");
break;
case "打7折":
cc = new CashRedbate("0.7");
break;
}//end switch
double totalprices = 0d;//金額
totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
*Convert.ToDouble(txtNumber2.Text));
//累加
total = total + totalprices;
listBox1.Items.Add("單價:" + txtNumber1.Text + "數量:" + txtNumber2.Text + "\t" +
combType.SelectedItem + "合計:" + totalprices.ToString());
lblmony.Text = total.ToString();
}
}//end createCashAccept
反思:
在第一個簡單工廠模式我們就把客戶端的判斷部分移動到了後端,但是在策略模式這裏我們又把判斷部分移到了客戶端。讓客戶端來選擇具體使用哪個策略。
解決方案:
我們可以把策略模式和簡單工廠模式結合使用,這樣即解決了算法可以靈活替換還把選擇部分又移動到了後端。
策略模式+簡單工廠模式:(只需要修改原來的CashFactory類和客戶端代碼)
CashFactory類
class CashFactory
{
CashSuper cs = null;//實例化父類
/// <summary>
/// 根據需要實例化對象
/// </summary>
/// <param name="type">需要實例化的對象名</param>
/// <returns>返回實例化之後的對象</returns>
public CashFactory(string type)
{
//判斷選擇了哪種優惠方案
switch (type)
{
case "正常收費":
cs = new CashNormal();
break;
case "滿300返100":
cs = new CashReturn("300", "100");
break;
case "打8折":
cs = new CashRedbate("0.8");
break;
case "打5折":
cs = new CashRedbate("0.5");
break;
case "打7折":
cs = new CashRedbate("0.7");
break;
}//end switch
}//end createCashAccept
/// <summary>
/// 根據具體實例化對象,調用方法。
/// </summary>
/// <param name="money">原價</param>
/// <returns>當前價格</returns>
public double GetResult(double money)
{
return cs.acceptCash(money);
}//end GetResult
}//end class CashFactory
客戶端(修改之後的)
double total = 0.0d;
private void butok_Click(object sender, EventArgs e)
{
//實例化策略工廠類
CashFactory cc = new CashFactory(combType.SelectedItem.ToString());
double totalprices = 0d;//金額
totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
*Convert.ToDouble(txtNumber2.Text));
//累加
total = total + totalprices;
listBox1.Items.Add("單價:" + txtNumber1.Text + "數量:" + txtNumber2.Text + "\t" +
combType.SelectedItem + "合計:" + totalprices.ToString());
lblmony.Text = total.ToString();
}
結果: