设计模式之简单模式与策略模式
最近在学习简单工厂模式与策略模式时,发现他们有很多相同之处,他们都是通过多态来实现不同子类的选取,比较难分辨,于是做了一下总结。
简单工厂模式用于比如算法之于加减乘除、水果之于苹果梨香蕉、文具之于笔尺,这些例子的共同特点就是具体、数量有限,不涉及复杂的算法,简单工厂模式只是解决了对象的创建问题,工厂类中封装了所有的选择过程,如果对象要增加、减少、变化,就要改动工厂,以至于代码的重写量增大,并且在操作过程中,客户需要指定一个参数给工厂,工厂按照参数选择出需要实例化的派生类。在简单工厂模式中,客户需要知道抽象基类和工厂类,工厂类用来生成对象,使用抽象基类的接口来完成工作。它的核心是“简单模式是用来封装所有对象的”。
下面是一个简单工厂模式的例子:
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