策略模式

前言

  1、面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同的属性和功能的对象的抽象集合才是类。

  2、简单工厂也能解决问题,但是只能解决对象的创建问题。

  3、策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的用户。

一、抽象算法类和子类

1      /// <summary>
2     /// 现金收取父类的抽取方法,收取现金,参数为原价,返回当前价
3     /// </summary>
4     public abstract class CashSuper
5     {
6         public abstract double acceptCash(double money);
7     }
 1      /// <summary>
 2     /// 正常收费
 3     /// </summary>
 4     public class CashNormal : CashSuper
 5     {
 6         /// <summary>
 7         /// 正常收费,原价返回
 8         /// </summary>
 9         /// <param name="money"></param>
10         /// <returns></returns>
11         public override double acceptCash(double money)
12         {
13             return money;
14             
15         }
16     }
 1     /// <summary>
 2     /// 打折收费子类
 3     /// </summary>
 4     public class CashRebate : CashSuper
 5     {
 6         private double moneyRebate = 1d;
 7         public CashRebate(string moneyRebate)
 8         {
 9             this.moneyRebate = double.Parse(moneyRebate);
10         }
11         public override double acceptCash(double money)
12         {
13             return money * moneyRebate;
14         }
15     }
 1    /// <summary>
 2     /// 返利收费子类
 3     /// </summary>
 4     public class CashReturn : CashSuper
 5     {
 6         private double moneyCondition = 0.0d;
 7         private double moneyReturn = 0.0d;
 8         /// <summary>
 9         /// 如:满300返100,则moneyCondition=300,moneyReturn=100
10         /// </summary>
11         /// <param name="moneyCondition"></param>
12         /// <param name="moneyReturn"></param>
13         public CashReturn(string moneyCondition, string moneyReturn)
14         {
15             this.moneyCondition = double.Parse(moneyCondition);
16             this.moneyReturn = double.Parse(moneyReturn);
17         }
18         public override double acceptCash(double money)
19         {
20             double result = money;
21             if (result > moneyCondition)
22             {
23                 //若大于返利条件,则需要减去返利值
24                 result = money - Math.Floor(money / moneyCondition) * moneyReturn;
25             }
26             return result;
27         }
28     }

二、简单工厂实现

  1、工厂 

 1     public class CashFactory
 2     {
 3         public static CashSuper CreateCashAccept(string type)
 4         {
 5             CashSuper cs = null;
 6             switch (type)
 7             {
 8                 case "正常收费":
 9                     cs = new CashNormal();
10                     break;
11                 case "满300返100":
12                     cs = new CashReturn("300","100");
13                     break;
14                 case "打8折":
15                     cs = new CashRebate("0.8");
16                     break;
17                 default:break;
18             }
19             return cs;
20         }
21     }
22 }

  2.工厂的客户端代码

     简单工厂的客户端代码,须知道(抽象类和工厂类)

 1      double total = 0.0d;
 2         private void btnOK_Click(object sender, EventArgs e)
 3         {
 4             double totalPrices = 0d;
 5             #region 简单工厂的客户端代码,须知道(抽象类和工厂类)
 6             CashSuper super = CashFactory.CreateCashAccept(cbxType.SelectedItem.ToString());
 7 
 8             totalPrices = super.acceptCash(Convert.ToDouble(txtPrice.Text))
 9                 * Convert.ToDouble(txtNum.Text);
10             total = total + totalPrices;
11             lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text
12                 + " " + cbxType.SelectedItem + " 合计: " + totalPrices.ToString());
13             lbResult.Text = total.ToString();
14             #endregion
15 
16 
17         }

三、策略模式

  1.策略类

  

 1  public class CashContext
 2     {
 3         private CashSuper cs;
 4         /// <summary>
 5         /// 通过构造函数,传入具体的收费策略
 6         /// </summary>
 7         /// <param name="super"></param>
 8         public CashContext(CashSuper super)
 9         {
10             this.cs = super;
11         }
12 
13         public double GetResult(double money)
14         {
15             //根据收费策略的不同,获得计算结果
16             return cs.acceptCash(money);
17         }
18     }

  2.策略类的客户端代码

   只有策略模式的客户端代码,须知道(策略类和各子类)

 1 public partial class Form1 : Form
 2     {
 3         public Form1()
 4         {
 5             InitializeComponent();
 6         }
 7 
 8         double total = 0.0d;
 9         private void btnOK_Click(object sender, EventArgs e)
10         {
11             double totalPrices = 0d;
12  
13             #region 只有策略模式的客户端代码,须知道(策略类和各子类)
14             CashContext cc = null;
15             switch (cbxType.SelectedItem.ToString())
16             {
17                 case "正常收费":
18                     cc = new CashContext(new CashNormal());
19                     break;
20                 case "满300返100":
21                     cc = new CashContext(new CashReturn("300", "100"));
22                     break;
23                 case "打8折":
24                     cc = new CashContext(new CashRebate("0.8"));
25                     break;
26                 default: break;
27             }
28             totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text))
29                 * Convert.ToDouble(txtNum.Text);
30             total = total + totalPrices;
31             lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text
32                 + " " + cbxType.SelectedItem + " 合计: " + totalPrices.ToString());
33             lbResult.Text = total.ToString();
34 
35             #endregion
36         }
37     }

四、策略模式和简单工厂模式结合

  1.策略类

  

 1  public class CashContext
 2     {
 3         private CashSuper cs;
 4         /// <summary>
 5         /// 工厂和策略模式结合
 6         /// </summary>
 7         /// <param name="super"></param>
 8         public CashContext(string type)
 9         {
10             switch (type)
11             {
12                 case "正常收费":
13                     cs = new CashNormal();
14                     break;
15                 case "满300返100":
16                     cs = new CashReturn("300", "100");
17                     break;
18                 case "打8折":
19                     cs = new CashRebate("0.8");
20                     break;
21                 default: break;
22             }
23         }
24         public double GetResult(double money)
25         {
26             //根据收费策略的不同,获得计算结果
27             return cs.acceptCash(money);
28         }
29     }

  2.客户端代码

    策略模式和简单工厂模式结合 只需知道策略类

 1     public partial class Form1 : Form
 2     {
 3         public Form1()
 4         {
 5             InitializeComponent();
 6         }
 7 
 8         double total = 0.0d;
 9         private void btnOK_Click(object sender, EventArgs e)
10         {
11             double totalPrices = 0d;
12 
13             #region 策略模式和简单工厂模式结合 只需知道策略类
14 
15             CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
16             totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text))
17                 * Convert.ToDouble(txtNum.Text);
18             total = total + totalPrices;
19             lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text
20                 + " " + cbxType.SelectedItem + " 合计: " + totalPrices.ToString());
21             lbResult.Text = total.ToString();
22 
23             #endregion
24         }
25     }

总结

  1、策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成时都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合。

  2、策略模式Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于分析去处这些算法中的公共功能。

  3、策略模式简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试

  4、可以用反射技术,消除switch分支,面对同样的需求,改动更小。

  参考书籍:大话设计模式

原文地址:https://www.cnblogs.com/hyunbar/p/9809569.html