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

策略模式:

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

以商店打折为例子:

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

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

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

1.策略模式

UML图形:

代码实现: 策略模式+简单工厂+反射_第1张图片

namespace 策略模式
{
    //抽象类---收费方式类(不同收费方式对应的价格的抽象)
    public abstract  class CashSuper
    {
        //抽象方法
        public abstract double acceptCash(double money);
    }
}
namespace 策略模式
{
    //价格正常类(子类)(对价格正常的抽象,继承于收费方式---正常收费方式)
    class CashNormal:CashSuper 
    {
        //对抽象方法acceptCash方法重写
        public override double acceptCash(double money)
        {
            return money;
        }
    }
}
namespace 策略模式
{
    //打折价格类(打折时候对应的不同价格子类---折扣收费方式)
    class CashRebate:CashSuper 
    {
        private double moneyRebate = 1d;
        //创建一个构建函数---初始化时必须输入折扣率
        public CashRebate (string moneyRebate)
        {
            //将字符创转换为等效的double数字
            this.moneyRebate = double.Parse(moneyRebate);
        }
        //重写方法acceptCash
        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }
}
using System;
namespace 策略模式
{
    //返利收费子类(达到返利条件会返值时的收费方式---返利收费方式)
    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);
        }

        //重写acceptCash方法
        public override double acceptCash(double money)
        {
            double result = money;
            if (money >= moneyCondition)
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            return result;
        }
    }
}
namespace 策略模式
{
    //这个类完成的工作:根据参数type返回对应的价钱(type对应的子类赋给了cs)
    class CashContext
    {      
        private CashSuper cs;

        //通过构造函数,传入具体的收费策略
        public CashContext(CashSuper csuper)
        {
            this.cs = csuper;
        }
        //根据收费策略的不同获得结果
        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }     
    }
}
using System;
using System.Windows.Forms;

namespace 策略模式
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
        }
        #region 策略模式
        double total = 0.0d;
        private void btnOK_Click(object sender, EventArgs e)
        {
            //用于总计
            double totalPrices = 0.0d;
            CashContext cc = null;
            //根据下拉选择框,将相应的策略对象作为参数,传入CashContext的对象中
            switch (comType.SelectedIndex.ToString())
            {
                case "正常收费":
                    cc=new CashContext (new CashNormal ());
                    break ;
                case "打八折":
                    cc = new CashContext(new CashRebate("0.8"));
                    break;
                case "满300返100":
                    cc=new CashContext (new CashReturn ("300","100"));
                    break;
            }
            //调用csuper的方法实现具体的收费计算
            totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);
            
            //显示
            total=total+totalPrices ;
            listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);
            labTotal.Text = total.ToString();
        }
        #endregion
        private void Form1_Load(object sender, EventArgs e)
        {
            //传入一个object类型的数组作为参数
            comType.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100" }); 
        
        }
        private void btnRebuilt_Click(object sender, EventArgs e)
        {
            txtAmount.Text = "";
            txtPrice.Text = "";
        }
    }
}

2.策略模式+简单工厂

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

改进的Cashtext代码:

namespace 策略模式
{
    //这个类完成的工作:根据参数type返回对应的价钱(type对应的子类赋给了cs)
    class CashContext
    {
        //实例化父类cs对象----调用公共的功能计算结果
        CashSuper csuper = null;

        //和工厂类相比,这个没有返回值
        //参数不是具体的收费策略对象,而是一个字符串,表示收费类型
        public CashContext(string type)
        {
            switch (type)
            {
                case "正常收费":
                   CashNormal cr0 = new CashNormal();
                   csuper = cr0;
                    break;
                case "打八折":
                    CashRebate cr1 = new CashRebate("0.8");
                    csuper = cr1;
                    break;
                case "满300减100":
                    CashReturn cr2 = new CashReturn("300", "100");
                    csuper = cr2;
                    break;
            }

        }
        public double GetResult(double money)
        {
            //csuper直接调用静态方法 返回对应的值
            return csuper.acceptCash(money);
        }    
    }
}

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

#region 策略模式+简单工厂
        double total = 0.0d;
        private void btnOK_Click(object sender, EventArgs e)
        {
            //用于总计
            double totalPrices = 0.0d;

            //根据下拉选择框,将相应的算法类型字符串传入CashContext的对象中
            CashContext csuper = new CashContext(comType.SelectedIndex.ToString());

            //调用csuper的方法实现具体的收费计算
            totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);
            
            //显示
            total=total+totalPrices ;
            listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);
            labTotal.Text = total.ToString();
        }
        #endregion

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

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

改进的Cashtext代码:

using System.Reflection;
namespace 策略模式
{
    class CashContext
    {   
        CashSuper csuper;
        private string Type;
        public CashContext(string Type)
        {
            //应用反射将原来的switch语句去掉
            this.Type = Type;
            csuper = (CashSuper)Assembly.Load("策略模式").CreateInstance("策略模式."+this.Type);
        }
         public double GetResult(double money)
        {
            //csuper直接调用静态方法 返回对应的值
            return csuper.acceptCash(money);
        }       
      }         
}

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

 #region 策略模式
        double total = 0.0d;
        private void btnOK_Click(object sender, EventArgs e)
        {
            //用于总计
            double totalPrices = 0.0d;

            CashContext csuper = new CashContext(strName(comType.SelectedIndex));

            //调用csuper的方法实现具体的收费计算
            totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text)) * Convert.ToDouble(txtAmount.Text);
            
            //显示
            total=total+totalPrices ;
            listRuselt.Items.Add("单价:" + txtPrice.Text + "  数量:" + txtAmount.Text + "  收费方式:" + comType.SelectedItem + "  总价:" + totalPrices);
            labTotal.Text = total.ToString();
        }
        //转换字符串函数
        string strType;
        public string strName(int type)
        {
            switch (type)
            {
                case 0:
                    strType = "CashNormal";
                    break;
                case 1:
                    strType = "CashRebate";
                    break;
                case 2:
                    strType = "CashReturn";
                    break;
            }
            return strType;
        }
        #endregion

你可能感兴趣的:(反射,策略模式)