在做一件事情完成一项任务时,往往会有很多个方法,这每一种方法都可以被称为策略,我们会根据不同的环境或条件,从众多方法中选取一个合适的方法来完成这件事情或任务。就像我们过年回家,回家的方式有很多种,比如坐飞机、乘坐火车、坐客车、走路等等,但是由于自身条件限制或者环境限制,我们往往会选择一个比较适合自己的回家方式回家。而我们选用的这个方法就可以称之为策略。
其实所谓的策略模式,是一种对象行为型模式,它定义了算法家族,然后分别对算法封装,让算法之间可以相互替换。这个模式让算法的变化,不会影响到使用算法的客户。它也被称之为政策模式。
策略模式的结构图:
Strategy类:
为Context定义了一系列的可以被重用的算法或者行为。
ConcreteStrategy类:
具体策略类,它封装了具体的算法或行为,继承Strategy类,有助于析取出这些算法中的公共功能。
策略模式应用举例:
代码结构图:
窗体设计图:
代码实现:
- double total = 0.0d;
- private void btnOK_Click(object sender, EventArgs e)
- {
- CashContext csuper = new CashContext(cmbType.SelectedItem.ToString());
- double totalPrices = 0d;
- totalPrices = csuper . GetResult (Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
- total = total + totalPrices;
- listBox1.Items.Add("单价:" + txtPrice.Text + "数量:" + txtNum.Text + "合计:" + totalPrices.ToString());
- lblTotal.Text =Convert .ToString ( total) ;
- }
- private void btnRef_Click(object sender, EventArgs e)
- {
- txtPrice.Text = "";
- txtNum.Text = "";
- listBox1.Text = "";
- lblTotal.Text = "";
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- cmbType.Items .AddRange (new object []{"正常收费","打八折","打七折","打五折","满300返100"});
- cmbType.SelectedIndex = 0;
- }
- }
- class CashContext
- {
- CashSuper cs = null;
- public CashContext(string type)//string type不是具体的收费策略,而是一个字符串,表示收费类型
- {
- switch (type )
- {
- case "正常收费":
- CashNormal cs0 = new CashNormal();
- cs = cs0;
- break;
- case "满300返100":
- CashReturn cs1 = new CashReturn("300","100");
- cs = cs1;
- break;
- case "打八折":
- CashRebate cs2 = new CashRebate("0.8");
- cs = cs2;
- break;
- }
- }
- public double GetResult(double money)
- {
- return cs.acceptCash(money);
- }
- }
- 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 - moneyReturn;
- return result;
- }
- }
策略模式的适用:
第一:如果一个系统中有很多类,而他们的区别也只是在于他们的行为,这时就可以使用策略模式从众多行为中选取其中一种行为。
第二:一个系统需要动态的从多种算法中选取某一种算法。
第三:系统有复杂的、与算法相关的数据结构,而我们又不希望客户端的客户知道这些数据结构,在具体策略中封装算法和相关数据结构,以确保算法的安全性,对算法保密。
第四:当不同的行为堆放在一个类中,就难免在执行时,会使用条件语句来选择某一种合适的行为。
策略模式的优点:
第一:简化了单元测试,每个算法都有自己的类,可以通过自己的接口来单独测试。
第二:可以避免使用多重条件转移语句,使之易维护。
第三:策略模式定义了一系列算法行为,所有算法完成的都是相同工作,只是实现不同,它可以以相同方式调用所有算法,减少各种与使用算法类之间的耦合。