策略模式定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的用户。
说明:
1.通过继承抽象策略实现多个具体策略方法处理,在一个类中传递不同的具体实例做为参数,获得不同的对象的算法,封装在同一个方法中,当这个类的实例调用这个封装了算法的方法时,因传入的对象参数的不同,获得的处理结果也不同。
2.通过传入的对象参数获得操作,改变一个方法的不同处理结果。
3.工厂方法是通过条件,建什么对象,策略模式是根据条件获得不同的算法。
3.每种算法单独维护即维护的查找,也简单了测试,不影响其他算法。
策略模式解析
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式可以为一些列相同的算法,提取一个公共的功能,通过参数,获得所需的算法执行。
例题中的打折、返利,都是实际收费其中的一种方式
策略模式+简单工厂模式,组合使用
书中商场管理软件(反射)
配置文件
<?xml version="1.0" encoding="utf-8" ?> <CashAcceptType> <type> <name>正常收费</name> <class>CashNormal</class> <para></para> </type> <type> <name>满300返100</name> <class>CashReturn</class> <para>300,100</para> </type> <type> <name>满200返50</name> <class>CashReturn</class> <para>200,50</para> </type> <type> <name>打8折</name> <class>CashRebate</class> <para>0.8</para> </type> <type> <name>打7折</name> <class>CashRebate</class> <para>0.7</para> </type> </CashAcceptType>
工厂超类
using System; using System.Collections.Generic; using System.Text; namespace 商场管理软件 { abstract class CashSuper { public abstract double acceptCash(double money);//用来定义一个支付接口 } }
using System; using System.Collections.Generic; using System.Text; namespace 商场管理软件 { class CashContext { private CashSuper cs; /// <summary> /// 设置策略类 /// </summary> /// <param name="csuper"></param> public void setBehavior(CashSuper csuper) { this.cs = csuper; } public double GetResult(double money) { return cs.acceptCash(money); } } }
算法实现类
using System; using System.Collections.Generic; using System.Text; namespace 商场管理软件 { /// <summary> /// 打折算法 /// </summary> 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; } } }
Form用户界面
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Reflection; namespace 商场管理软件 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } DataSet ds;//用于存放配置文件信息 double total = 0.0d;//用于总计 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(); //根据用户的选项,查询用户选择项的相关行 DataRow dr = ((DataRow[])ds.Tables[0].Select("name='" + cbxType.SelectedItem.ToString()+"'"))[0]; //声明一个参数的对象数组 object[] args =null; //若有参数,则将其分割成字符串数组,用于实例化时所用的参数 if (dr["para"].ToString() != "") args = dr["para"].ToString().Split(','); //通过反射实例化出相应的算法对象,调用策略类的设置策略方法,要注意一下反射实例化一个算法对象的时候 Object[] 的参数在此使用了 //上一个实例没有使用反射的这里是通过判断来硬编码选择实例化制定的算法实例 cc.setBehavior((CashSuper)Assembly.Load("商场管理软件").CreateInstance("商场管理软件." + dr["class"].ToString(), false, BindingFlags.Default, null, args, null, null)); double totalPrices = 0d; totalPrices = cc.GetResult(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(); } /// <summary> /// 清空控件信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnClear_Click(object sender, EventArgs e) { total = 0d; txtPrice.Text = "0.00"; txtNum.Text = "1"; lbxList.Items.Clear(); lblResult.Text = "0.00"; } } }
结果显示