策略模式+简单工厂+反射

策略模式:

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

以商店打折为例子:

商店没有做活动,那么收费就是正常收费

商店如果进行活动,那么就会有优惠方式;比如是打折,或者是满300返100等等

这些都是算法,算法本省就是一种策略,他的特点就是完成的工作相同,只是实现不同;所以策略模式就是讲这些算法封装起来

1.策略模式

UML图形:

代码实现: 

[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">namespace 策略模式  
  2. {  
  3.     //抽象类---收费方式类(不同收费方式对应的价格的抽象)  
  4.     public abstract  class CashSuper  
  5.     {  
  6.         //抽象方法  
  7.         public abstract double acceptCash(double money);  
  8.     }  
  9. }  
  10. </span>  
[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">namespace 策略模式  
  2. {  
  3.     //价格正常类(子类)(对价格正常的抽象,继承于收费方式---正常收费方式)  
  4.     class CashNormal:CashSuper   
  5.     {  
  6.         //对抽象方法acceptCash方法重写  
  7.         public override double acceptCash(double money)  
  8.         {  
  9.             return money;  
  10.         }  
  11.     }  
  12. }</span>  
[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">namespace 策略模式  
  2. {  
  3.     //打折价格类(打折时候对应的不同价格子类---折扣收费方式)  
  4.     class CashRebate:CashSuper   
  5.     {  
  6.         private double moneyRebate = 1d;  
  7.         //创建一个构建函数---初始化时必须输入折扣率  
  8.         public CashRebate (string moneyRebate)  
  9.         {  
  10.             //将字符创转换为等效的double数字  
  11.             this.moneyRebate = double.Parse(moneyRebate);  
  12.         }  
  13.         //重写方法acceptCash  
  14.         public override double acceptCash(double money)  
  15.         {  
  16.             return money * moneyRebate;  
  17.         }  
  18.     }  
  19. }  
  20. </span>  
[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">using System;  
  2. namespace 策略模式  
  3. {  
  4.     //返利收费子类(达到返利条件会返值时的收费方式---返利收费方式)  
  5.     class CashReturn:CashSuper   
  6.     {  
  7.         //声明返利条件和返利值(私有--不可访问)  
  8.         private double moneyCondition = 0.0d;  
  9.         private double moneyReturn = 0.0d;  
  10.   
  11.         //构造函数--初始化时必须输入返利条件和返利值  
  12.         public CashReturn(string moneyCondition, string moneyReturn)  
  13.         {  
  14.             this.moneyCondition = double.Parse(moneyCondition);  
  15.             this.moneyReturn = double.Parse(moneyReturn);  
  16.         }  
  17.   
  18.         //重写acceptCash方法  
  19.         public override double acceptCash(double money)  
  20.         {  
  21.             double result = money;  
  22.             if (money >= moneyCondition)  
  23.                 result = money - Math.Floor(money / moneyCondition) * moneyReturn;  
  24.             return result;  
  25.         }  
  26.     }  
  27. }  
  28. </span>  
[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">namespace 策略模式  
  2. {  
  3.     //这个类完成的工作:根据参数type返回对应的价钱(type对应的子类赋给了cs)  
  4.     class CashContext  
  5.     {        
  6.         private CashSuper cs;  
  7.   
  8.         //通过构造函数,传入具体的收费策略  
  9.         public CashContext(CashSuper csuper)  
  10.         {  
  11.             this.cs = csuper;  
  12.         }  
  13.         //根据收费策略的不同获得结果  
  14.         public double GetResult(double money)  
  15.         {  
  16.             return cs.acceptCash(money);  
  17.         }       
  18.     }  
  19. }  
  20. </span>  
[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">using System;  
  2. using System.Windows.Forms;  
  3.   
  4. namespace 策略模式  
  5. {  
  6.     public partial class Form1 : Form  
  7.     {  
  8.         public Form1()  
  9.         {  
  10.             InitializeComponent();  
  11.               
  12.         }  
  13.         #region 策略模式  
  14.         double total = 0.0d;  
  15.         private void btnOK_Click(object sender, EventArgs e)  
  16.         {  
  17.             //用于总计  
  18.             double totalPrices = 0.0d;  
  19.             CashContext cc = null;  
  20.             //根据下拉选择框,将相应的策略对象作为参数,传入CashContext的对象中  
  21.             switch (comType.SelectedIndex.ToString())  
  22.             {  
  23.                 case "正常收费":  
  24.                     cc=new CashContext (new CashNormal ());  
  25.                     break ;  
  26.                 case "打八折":  
  27.                     cc = new CashContext(new CashRebate("0.8"));  
  28.                     break;  
  29.                 case "满300返100":  
  30.                     cc=new CashContext (new CashReturn ("300","100"));  
  31.                     break;  
  32.             }  
  33.             //调用csuper的方法实现具体的收费计算  
  34.             totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);  
  35.               
  36.             //显示  
  37.             total=total+totalPrices ;  
  38.             listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);  
  39.             labTotal.Text = total.ToString();  
  40.         }  
  41.         #endregion  
  42.         private void Form1_Load(object sender, EventArgs e)  
  43.         {  
  44.             //传入一个object类型的数组作为参数  
  45.             comType.Items.AddRange(new object[] { "正常收费""打八折""满300返100" });   
  46.           
  47.         }  
  48.         private void btnRebuilt_Click(object sender, EventArgs e)  
  49.         {  
  50.             txtAmount.Text = "";  
  51.             txtPrice.Text = "";  
  52.         }  
  53.     }  
  54. }</span>  

2.策略模式+简单工厂

策略模式需要在客户端判断用哪个算法,那么为了解决这个问题就可以将策略模式和简单工厂结合起来。具体的方法就是简单工厂与策略模式中的Context类结合

改进的Cashtext代码:

[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">namespace 策略模式  
  2. {  
  3.     //这个类完成的工作:根据参数type返回对应的价钱(type对应的子类赋给了cs)  
  4.     class CashContext  
  5.     {  
  6.         //实例化父类cs对象----调用公共的功能计算结果  
  7.         CashSuper csuper = null;  
  8.   
  9.         //和工厂类相比,这个没有返回值  
  10.         //参数不是具体的收费策略对象,而是一个字符串,表示收费类型  
  11.         public CashContext(string type)  
  12.         {  
  13.             switch (type)  
  14.             {  
  15.                 case "正常收费":  
  16.                    CashNormal cr0 = new CashNormal();  
  17.                    csuper = cr0;  
  18.                     break;  
  19.                 case "打八折":  
  20.                     CashRebate cr1 = new CashRebate("0.8");  
  21.                     csuper = cr1;  
  22.                     break;  
  23.                 case "满300减100":  
  24.                     CashReturn cr2 = new CashReturn("300""100");  
  25.                     csuper = cr2;  
  26.                     break;  
  27.             }  
  28.   
  29.         }  
  30.         public double GetResult(double money)  
  31.         {  
  32.             //csuper直接调用静态方法 返回对应的值  
  33.             return csuper.acceptCash(money);  
  34.         }      
  35.     }  
  36. }</span>  

客户端代码(主要部分):

[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">#region 策略模式+简单工厂  
  2.         double total = 0.0d;  
  3.         private void btnOK_Click(object sender, EventArgs e)  
  4.         {  
  5.             //用于总计  
  6.             double totalPrices = 0.0d;  
  7.   
  8.             //根据下拉选择框,将相应的算法类型字符串传入CashContext的对象中  
  9.             CashContext csuper = new CashContext(comType.SelectedIndex.ToString());  
  10.   
  11.             //调用csuper的方法实现具体的收费计算  
  12.             totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);  
  13.               
  14.             //显示  
  15.             total=total+totalPrices ;  
  16.             listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);  
  17.             labTotal.Text = total.ToString();  
  18.         }  
  19.         #endregion</span>  

3.策略模式+简单工厂+反射

为了避免每次添加新的打折方法都要修改switch语句,我们利用反射将switch语句替换掉

改进的Cashtext代码:

[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">using System.Reflection;  
  2. namespace 策略模式  
  3. {  
  4.     class CashContext  
  5.     {     
  6.         CashSuper csuper;  
  7.         private string Type;  
  8.         public CashContext(string Type)  
  9.         {  
  10.             //应用反射将原来的switch语句去掉  
  11.             this.Type = Type;  
  12.             csuper = (CashSuper)Assembly.Load("策略模式").CreateInstance("策略模式."+this.Type);  
  13.         }  
  14.          public double GetResult(double money)  
  15.         {  
  16.             //csuper直接调用静态方法 返回对应的值  
  17.             return csuper.acceptCash(money);  
  18.         }         
  19.       }           
  20. }</span>  

客户端代码(主要部分):

[csharp] view plain copy print ?
  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"> #region 策略模式  
  2.         double total = 0.0d;  
  3.         private void btnOK_Click(object sender, EventArgs e)  
  4.         {  
  5.             //用于总计  
  6.             double totalPrices = 0.0d;  
  7.   
  8.             CashContext csuper = new CashContext(strName(comType.SelectedIndex));  
  9.   
  10.             //调用csuper的方法实现具体的收费计算  
  11.             totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);  
  12.               
  13.             //显示  
  14.             total=total+totalPrices ;  
  15.             listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);  
  16.             labTotal.Text = total.ToString();  
  17.         }</span>  
[csharp] view plain copy print ?
    1. <span style="font-family:KaiTi_GB2312;font-size:18px;">        //转换字符串函数  
    2.         string strType;  
    3.         public string strName(int type)  
    4.         {  
    5.             switch (type)  
    6.             {  
    7.                 case 0:  
    8.                     strType = "CashNormal";  
    9.                     break;  
    10.                 case 1:  
    11.                     strType = "CashRebate";  
    12.                     break;  
    13.                 case 2:  
    14.                     strType = "CashReturn";  
    15.                     break;  
    16.             }  
    17.             return strType;  
    18.         }  
    19.         #endregion</span> 
原文地址:https://www.cnblogs.com/fengyv/p/3052545.html