面向?qū)ο缶幊?,并不是類越多越好,類的劃分是為了封裝,但分類的基礎(chǔ)是抽象,具有相同屬性和功能的對(duì)象的抽象集合才是類
我們?cè)贛artin編寫的《代碼整潔之道》中對(duì)類的看法,類應(yīng)該短?。ㄩL(zhǎng)度不應(yīng)該容納一個(gè)if嵌套語句,20行封頂),而且只做一件事,做好這件事。強(qiáng)調(diào)的是簡(jiǎn)潔和優(yōu)雅,但是不沒說類越多越好。
這里我們可以明白我們應(yīng)該用什么態(tài)度來看待和創(chuàng)建類,對(duì)我們的工程很重要。
策略模式的定義:
策略模式UML:
主要的東西還是Context的配置,傳入具體的策略,然后返回出對(duì)應(yīng)策略的的結(jié)果。
下面是收費(fèi)策略的一個(gè)事例
//收費(fèi)策略Context class CashContext { //聲明一個(gè)現(xiàn)金收費(fèi)父類對(duì)象 private CashSuper cs; //設(shè)置策略行為,參數(shù)為具體的現(xiàn)金收費(fèi)子類(正常,打折或返利) public CashContext(CashSuper csuper) { this.cs = csuper; } //得到現(xiàn)金促銷計(jì)算結(jié)果(利用了多態(tài)機(jī)制,不同的策略行為導(dǎo)致不同的結(jié)果) public double GetResult(double money) { return cs.acceptCash(money); } }
簡(jiǎn)單工廠與策略模式的結(jié)合是比較常見的。
簡(jiǎn)單工廠與策略模式結(jié)合事例(把客戶端的switch給封裝了,封裝了變化的體現(xiàn))
View Code //現(xiàn)金收取工廠 class CashContext { CashSuper cs = null ; //根據(jù)條件返回相應(yīng)的對(duì)象 public CashContext(string type) { switch (type) { case "正常收費(fèi)" : CashNormal cs0 = new CashNormal(); cs = cs0; break; case "滿300返100" : CashReturn cr1 = new CashReturn( "300", "100" ); cs = cr1; break; case "打8折" : CashRebate cr2 = new CashRebate( "0.8"); cs = cr2; break; } } public double GetResult(double money) { return cs.acceptCash(money); } }
但是單是試用策略模式客戶端如下:
對(duì)比一下可以知道后則只暴露了一個(gè)配置類Content而前者必須要客戶端知道除了配置類其他的類,這樣前者耦合性更低。
后則也把判斷從客戶端的判斷條件給移除了,這樣客戶端判斷壓力減小了。
在定義上該模式是封裝算法的,但是我?guī)讉€(gè)人建議學(xué)習(xí)設(shè)計(jì)模式千萬不要因?yàn)槟J蕉J剑蛐枨蠛驮O(shè)計(jì)而模式。因此
只要是不同時(shí)間要應(yīng)用不同的業(yè)務(wù)那么這時(shí)候就該考慮策略模式了 。
總結(jié):
策略模式與簡(jiǎn)單工廠的區(qū)別:
主要就是用Content上下文配置,客戶端通過條件判斷傳遞一個(gè)事例,然后實(shí)例化對(duì)應(yīng)對(duì)像,
加上一個(gè)GetResult方法算出結(jié)果,客戶端調(diào)用該方法返回結(jié)果得到值。這里對(duì)算法進(jìn)行了封裝
--------------------------------------------------------------------------------------------------------------
而簡(jiǎn)單工廠就是客戶端只需要傳遞一個(gè)判斷標(biāo)識(shí),然后工廠根據(jù)標(biāo)識(shí)做出判斷應(yīng)該返回什么事例,
客戶端拿到返回事例對(duì)象,通過調(diào)用該對(duì)象得到返回結(jié)果。這里對(duì)判斷后置了減少了客戶端判斷壓力
策略模式與簡(jiǎn)單工廠策略模式區(qū)別:
就是對(duì)前者優(yōu)點(diǎn)的結(jié)合。
既封裝了算法也減少了客戶端判斷壓力
---------------------------------------------------------------------------------------------------------------
到此為止如果需求變動(dòng)(增加一種算法)那么我們還是需要修改switch 條件
增加一個(gè)具體的算法類。
那么該如何讓其不改動(dòng)代碼呢?對(duì)就是反射
我們以一種數(shù)據(jù)驅(qū)動(dòng)的形式來處理這個(gè)問題,下拉框內(nèi)存我們通過讀取配置文件獲取
客戶端只需要傳入類名和需要的參數(shù)即可如下:
View CodeDataSet ds;//用于存放配置文件信息 double total = 0.0d;//用于總計(jì) private void Form1_Load(object sender, EventArgs e) { //讀配置文件 ds = new DataSet(); ds.ReadXml(Application.StartupPath + "\\CashAcceptType.xml"); //將讀取到的記錄綁定到下拉列表框中 foreach (DataRowView dr in ds.Tables[0].DefaultView) { cbxType.Items.Add(dr["name"].ToString()); } cbxType.SelectedIndex = 0; } private void btnOk_Click(object sender, EventArgs e) { CashContext cc = new CashContext(); //根據(jù)用戶的選項(xiàng),查詢用戶選擇項(xiàng)的相關(guān)行 DataRow dr = ((DataRow[])ds.Tables[0].Select("name='" + cbxType.SelectedItem.ToString()+"'"))[0]; //聲明一個(gè)參數(shù)的對(duì)象數(shù)組 object[] args =null; //若有參數(shù),則將其分割成字符串?dāng)?shù)組,用于實(shí)例化時(shí)所用的參數(shù) if (dr["para"].ToString() != "") args = dr["para"].ToString().Split(','); //通過反射實(shí)例化出相應(yīng)的算法對(duì)象 cc.setBehavior(dr["class"].ToString(), args); double totalPrices = 0d; totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text)); total = total + totalPrices; lbxList.Items.Add("單價(jià):" + txtPrice.Text + " 數(shù)量:" + txtNum.Text + ""+cbxType.SelectedItem+ " 合計(jì):" + totalPrices.ToString()); lblResult.Text = total.ToString(); }
而我們的配置類就應(yīng)該是實(shí)現(xiàn)反射的類如下:
View Codeclass CashContext { private CashSuper cs; public void setBehavior(string className, object[] args) { this.cs = (CashSuper)Assembly.Load("商場(chǎng)管理軟件").CreateInstance("商場(chǎng)管理軟件." + className, false, BindingFlags.Default, null, args, null, null); } public double GetResult(double money) { return cs.acceptCash(money); } }
到此為止我們使用簡(jiǎn)單工廠策略模式+反射實(shí)現(xiàn)了一種數(shù)據(jù)驅(qū)動(dòng)的方式實(shí)現(xiàn)了代碼0修改。
數(shù)據(jù)驅(qū)動(dòng)是我們常用的一種設(shè)計(jì)方案,這是一種偉大的進(jìn)步,從數(shù)據(jù)驅(qū)動(dòng)直到今天的腳本游戲引擎比如說unity3d............扯遠(yuǎn)了....下一篇來吧....................................
如果需要可以下載源碼:D
http://www.cnblogs.com/Wonder1989/archive/2013/03/27/2985275.html
本博客不在跟新 請(qǐng)移步http://www.cnblogs.com/Wonder1989