設計模式之簡單模式與策略模式
最近在學習簡單工廠模式與策略模式時,發現他們有很多相同之處,他們都是通過多態來實現不同子類的選取,比較難分辨,於是做了一下總結。
簡單工廠模式用於比如算法之於加減乘除、水果之於蘋果梨香蕉、文具之於筆尺,這些例子的共同特點就是具體、數量有限,不涉及複雜的算法,簡單工廠模式隻是解決了對象的創建問題,工廠類中封裝了所有的選擇過程,如果對象要增加、減少、變化,就要改動工廠,以至於代碼的重寫量增大,並且在操作過程中,客戶需要指定一個參數給工廠,工廠按照參數選擇出需要實例化的派生類。在簡單工廠模式中,客戶需要知道抽象基類和工廠類,工廠類用來生成對象,使用抽象基類的接口來完成工作。它的核心是“簡單模式是用來封裝所有對象的”。
下麵是一個簡單工廠模式的例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 簡單工廠模式 { class Program { static void Main(string[] args) { Operation oper; oper = OperationFactory.createOperate("+"); oper.NumberA = 1; oper.NumberB = 4; double result = oper.GetResult(); Console.WriteLine("結果是:" + result); } public class Operation//抽象類 { private double _numberA = 0; private double _numberB = 0; public double NumberA { get { return _numberA; } set { _numberA = value; } } public double NumberB { get { return _numberB; } set { _numberB = value; } } public virtual double GetResult() { double result = 0; return result; } } class OperationAdd : Operation//基類:加法 { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } } class OperationSub : Operation//減法 { public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } } class OperationMul : Operation//乘法 { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } } class OperationDiv : Operation//除法 { public override double GetResult() { double result = 0; if (NumberB == 0) throw new Exception("除數不能為0。"); result = NumberA / NumberB; return result; } } //工廠類 public class OperationFactory { public static Operation createOperate(string operate) { Operation oper = null; switch (operate ) { case "+": oper = new OperationAdd(); break; case "-": oper = new OperationSub(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationDiv(); break; } return oper; } } } }由於產品對象形式經常改變,使用簡單工廠模式則會導致代碼重新編寫,而策略模式則避免了這一點,它定義了算法家族,分別封裝起來,讓他們之間可以相互替換,算法的變化不會影響到客戶對算法的使用,適用於大量複雜運算,它和簡單工廠模式的區別就是,它沒有工廠類,而是將工廠類的代碼寫到了客戶端,客戶端包括具有各種功能的代碼,策略模式在使用時首先要創建一個類,將該類的對象傳遞進去,通過該對象調用不同的算法,下麵的Context就是這個作用,它將使用選擇對象的工廠交給了使用該模式的用戶.它的核心是:策略模式是用來封裝算法的,但在實踐中,我們發現可以用它來封裝幾乎任何類型的規則,隻要在分析過程中遇到需要在不同時間應用不同的業務規則,就可以考慮使用策略模式處理這種變化的可能性.
下麵是一段策略模式的例子:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ce { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { cbxType.Items.Add("正常收費"); cbxType .Items .Add ("打折收費"); cbxType .Items.Add ("返利收費"); } private void btnOk_Click(object sender, EventArgs e) { CashSuper csuper=CashFactory .CreateCashAccept (cbxType.SelectedItem.ToString()); } //現金收取抽象類 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 - Math.Floor(money / moneyCondition) * moneyReturn; return result; } } //現金收費工廠類 class CashFactory { public static CashSuper CreateCashAccept(string type)//現金收取工廠 { CashSuper cs=null; switch (type) { case "正常收費": cs=new CashNormal (); break ; case "滿300返100": CashReturn cr1=new CashReturn ("300","100"); cs=cr1; break ; case "打8折": CashRebate cr2=new CashRebate ("0.8"); cs=cr2; break ; } return cs ; } } class CashContext { private CashSuper cs;//聲明一個CashSuper對象; public CashContext (CashSuper csuper)//通過構造方法,傳入具體的收費策略; { this.cs=csuper ; } public double GetResult(double money) { return cs.acceptCash (money );//根據收費策略不同獲得計算結果; } } //客戶端窗體程序 double total=0.0d; private void bntOk_Click(object sender, EventArgs e) { CashContext cc=null ; switch (cbxType .SelectedItem .ToString ()) { case "正常收費": cc=new CashContext (new CashNormal ()); break; case "滿300返100": cc=new CashContext (new CashReturn ("300","100")); break ; case "打8折": cc=new CashContext (new CashRebate ("0.8")); break ; } CashSuper csuper = CashFactory.CreateCashAccept(cbxType.SelectedItem.ToString()); double totalPrices=0d; //通過多態,可以得到收費的結果 totalPrices =csuper .acceptCash (Convert .ToDouble(txtPrice .Text)*Convert.ToDouble (txtNum.Text ) ); total=total+totalPrices; lbxList .Items.Add("單價:"+txtPrice.Text +"數量:"+txtNum.Text +" "+cbxType.SelectedItem +"合計:" +totalPrices .ToString ()); lblResult.Text =total .ToString (); } } }大家通過這兩段代碼和我的描述應該對這兩種模式有所了解了,理解的還不夠深刻,希望大家多多指出!
最後更新:2017-04-03 12:55:04