【設計模式】(一)-簡單工廠模式和策略模式
前言
最近開始和春哥,張鐸 ,銀平討論設計模式,成立了一個小菜變大鳥的小組,每天討論一個模式,並且把這個模式搞懂,每學一個新的模式,再回顧一下之前學的模式。這兩天學了簡單工廠模式和策略模式,發現兩個模式有很多相同之處,下面用商場促銷的例子來對兩個模式總結一下。
簡單工廠模式
1.首先建立一個抽象類,用以子類繼承,定義了抽象方法 acceptCash() 方法傳入引數 money
abstract class CashSuper
{
public abstract double acceptCash(double money);
}
2.這裡定義了三個子類,分別處理 正常收費 , 打折 , 滿300返100 三種收費方法。
class CashNormal : CashSuper { public override double acceptCash(double money) { return money; } } class CashRebate : CashSuper { private double rebate = 1d; public CashRebate(string Rebate) { rebate = Convert.ToDouble(Rebate); } public override double acceptCash(double Money) { return Money * rebate; } } 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 - Math.Floor(money / moneyCondition) * moneyReturn; return result; } }
大話模式的第一章的簡單工廠模式是用父類實現多型,這裡體現的是用抽象類實現多型。
3.下面是工廠類
public class CashFactory { public static CashSuper createCashAccept(string type) { CashSuper cs = null; switch (type) { case "正常收費": cs = new CashNormal(); break; case "打八折": cs = new CashRebate("0.8"); break; case "打七折": cs = new CashRebate("0.7"); break; case "滿300返100": cs = new CashReturn("300","100"); break ; } return cs; }
4.然後是客戶端的程式碼
public Form1()
{
InitializeComponent();
}
double total = 0.0d;
private void button1_Click(object sender, EventArgs e)
{
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add("單價:" + txtPrice.Text +"數量:" + txtNum.Text + cbxType.SelectedItem + "合計:" + totalPrices.ToString());
label4.Text = total.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] { "正常收費", "打八折", "滿300返100"});
cbxType.SelectedIndex = 0;
}
}
首先建立 CashSuper 物件,呼叫工廠類的 createCashAccept()方法,根據傳入的字串(正常收費,打八折)返回相應的 CashSuper 物件,然後執行剛才複寫的 acceptCash()方法,傳入引數 money 進行計算。
優點:通過使用工廠類,外界可以從直接建立具體產品物件的尷尬局面擺脫出來,僅僅需要負責“消費”物件就可以了。而不必管這些物件究竟如何建立及如何組織的.明確了各自的職責和權利,有利於整個軟體體系結構的優化。
缺點:由於工廠類集中了所有例項的建立邏輯,違反了高內聚責任分配原則,將全部建立邏輯集中到了一個工廠類中;它所能建立的類只能是事先考慮到的,如果需要新增新的類,則就需要改變工廠類了。
策略模式
策略模式的概念:策略模式定義了演算法家族,分別封裝起來,讓他們之間可以相互替換,策略模式讓演算法的變化不會影響到使用演算法的客戶。
同樣的例子使用策略模式更改一下,CashSuper和三種處理方法不用更改,只需在簡單工廠基礎上新增 CashContext 類:
class CashContext
{
private CashSuper cs;
public CashContext(CashSuper csuper)
{
this.cs = csuper;
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
客戶端程式碼如下,將相應的策略物件作為引數傳入 CashContext 物件中:
private void button1_Click(object sender, EventArgs e)
{
CashContext cc = null ;
switch(cbxType .SelectedItem.ToString())
{
case "正常收費":
cc = new CashContext (new CashNormal());
break ;
case "打八折":
cc = new CashContext (new CashRebate("0.8"));
break ;
case "滿300返100":
cc = new CashContext (new CashReturn("300","100"));
break ;
}
double totalPrice = 0d;
totalPrice = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
比較簡單工廠的方法知道,簡單工廠需要客戶端認識兩個類 CashSuper 和 CashFactory ,而策略模式客戶端只需要認識 CashContext 類就可以了,使得具體的收費演算法徹底與客戶端分離,耦合度更加降低。
策略與簡單工廠結合
改造後的CashContext:將例項化具體策略的過程由客戶端轉移到Context類種。
class CashContext
{
CashSuper cs = null;
public CashContext(string type)
{
switch (type)
{
case "正常收費":
CashNormal cs0 = new CashNormal();
cs = cs0;
break;
case "滿300返100":
CashReturn cr1 = new CashReturn("300","100");
cs = cr1;
break;
case "打八折":
CashRebate cr2 = new CashRebate("0.8");
cs = cr2;
break;
}
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
}
客戶端端程式碼如下:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double total = 0.0d;
private void button1_Click(object sender, EventArgs e)
{
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add("單價:" + txtPrice.Text +"數量:" + txtNum.Text + cbxType.SelectedItem + "合計:" + totalPrices.ToString());
label4.Text = total.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] { "正常收費", "打八折", "滿300返100"});
cbxType.SelectedIndex = 0;
}
}
總結
比較簡單工廠的方法知道,簡單工廠需要客戶端認識兩個類 CashSuper 和 CashFactory ,而策略模式客戶端只需要認識 CashContext 類就可以了,使得具體的收費演算法徹底與客戶端分離,耦合度更加降低。
剛開始學,感覺學的還不夠深入,如有錯誤,還望指教。