在做一件事情完成一項任務時,往往會有很多個方法,這每一種方法都可以被稱為策略,我們會根據不同的環境或條件,從眾多方法中選取一個合適的方法來完成這件事情或任務。就像我們過年回家,回家的方式有很多種,比如坐飛機、乘坐火車、坐客車、走路等等,但是由於自身條件限制或者環境限制,我們往往會選擇一個比較適合自己的回家方式回家。而我們選用的這個方法就可以稱之為策略。
其實所謂的策略模式,是一種對象行為型模式,它定義了算法家族,然後分別對算法封裝,讓算法之間可以相互替換。這個模式讓算法的變化,不會影響到使用算法的客戶。它也被稱之為政策模式。
策略模式的結構圖:
Strategy類:
為Context定義了一系列的可以被重用的算法或者行為。
ConcreteStrategy類:
具體策略類,它封裝了具體的算法或行為,繼承Strategy類,有助於析取出這些算法中的公共功能。
策略模式應用舉例:
代碼結構圖:
窗體設計圖:
代碼實現:
[csharp]
double total = 0.0d;
private void btnOK_Click(object sender, EventArgs e)
{
CashContext csuper = new CashContext(cmbType.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper . GetResult (Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
listBox1.Items.Add("單價:" + txtPrice.Text + "數量:" + txtNum.Text + "合計:" + totalPrices.ToString());
lblTotal.Text =Convert .ToString ( total) ;
}
private void btnRef_Click(object sender, EventArgs e)
{
txtPrice.Text = "";
txtNum.Text = "";
listBox1.Text = "";
lblTotal.Text = "";
}
private void Form1_Load(object sender, EventArgs e)
{
cmbType.Items .AddRange (new object []{"正常收費","打八折","打七折","打五折","滿300返100"});
cmbType.SelectedIndex = 0;
}
}
class CashContext
{
CashSuper cs = null;
public CashContext(string type)//string type不是具體的收費策略,而是一個字符串,表示收費類型
{
switch (type )
{
case "正常收費":
CashNormal cs0 = new CashNormal();
cs = cs0;
break;
case "滿300返100":
CashReturn cs1 = new CashReturn("300","100");
cs = cs1;
break;
case "打八折":
CashRebate cs2 = new CashRebate("0.8");
cs = cs2;
break;
}
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
abstract class CashSuper //現金收取的抽象類
{
public abstract double acceptCash(double money);
}
class CashNormal : CashSuper //子類之正常收費類
{
public override double acceptCash(double money)
{
return money;
}
}
class CashRebate : CashSuper //打折收費類
{
private double moneyRebate = 1d;
public CashRebate (string moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
}
public override double acceptCash(double money)
{
return money * moneyRebate;
}
}
class CashReturn : CashSuper //滿多少返回多少類
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money)
{
double result = money;
if (money >= moneyCondition)
result = money - moneyReturn;
return result;
}
}
策略模式的適用:
第一:如果一個系統中有很多類,而他們的區別也只是在於他們的行為,這時就可以使用策略模式從眾多行為中選取其中一種行為。
第二:一個系統需要動態的從多種算法中選取某一種算法。
第三:系統有復雜的、與算法相關的數據結構,而我們又不希望客戶端的客戶知道這些數據結構,在具體策略中封裝算法和相關數據結構,以確保算法的安全性,對算法保密。
第四:當不同的行為堆放在一個類中,就難免在執行時,會使用條件語句來選擇某一種合適的行為。
策略模式的優點:
第一:簡化了單元測試,每個算法都有自己的類,可以通過自己的接口來單獨測試。
第二:可以避免使用多重條件轉移語句,使之易維護。
第三:策略模式定義了一系列算法行為,所有算法完成的都是相同工作,只是實現不同,它可以以相同方式調用所有算法,減少各種與使用算法類之間的耦合。