zoukankan      html  css  js  c++  java
  • 策略模式+简单工厂+反射

    策略模式:

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

    以商店打折为例子:

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

    商店如果进行活动,那么就会有优惠方式;比如是打折,或者是满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> 
  • 相关阅读:
    SysUtils.UpperCase、SysUtils.LowerCase 大小写转换
    Sql Server 2005 数据库备份还原后出现“受限制用户”问题的解决
    为什么要跪谢
    【基础】C#卸载快捷方式添加
    DataTable 复制 DataRow 出现 “该行已经属于另一个表”错误的解决办法
    将int型转化成五位字符串,前面用0填充
    C#嵌套类的使用方法及特性(转)
    net内存回收与Dispose﹐Close﹐Finalize方法(转)
    sqlhelper中文注释版(转)
    windows2003消息队列的安装
  • 原文地址:https://www.cnblogs.com/fengyv/p/3052545.html
Copyright © 2011-2022 走看看