菜鸟升级记——策略模式

  策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法

  • 举例:
    • 从北京到青岛的方式?
      1)飞机
      2)高铁
      3)火车
      4)长途汽车
      5)私家车
      6)自行车
      7)走路

  通过以上方式,我们都可以达到去青岛的目的,那么列出的这些方法,就是我们选择的策略。 策略模式对策略进行抽象,策略的意思就是方法,所以也就是对方法的抽象。

概述

  策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装到具有公共接口的独立的类中,使每个算法可以相互替代,也使算法本身和使用算法的客户端分割开来,相互独立”。

模式中的角色

  • —抽象策略角色(Stratege)
    策略类,通常由一个接口或者抽象类实现。此角色给出所有的具体策略类所需的接口。用来约束一系列具体的策略算法,策略上下文角色ConcreteStrategy使用此策略接口来调用具体的策略所实现的算法
  • —具体策略角色(Concrete Stratege)
    包装了相关的算法和行为。
  • —环境角色(Context)
    持有一个策略类的引用,最终给客户端调用。策略上下文,负责和具体的策略实现交互,通常策略上下文对象会持有一个真正的策略实现对象,策略上下文还可以让具体的策略实现从其中获取相关数据,回调策略上下文对象的方法。

代码

    //策略类
    class CashContext
    {
        //声明一个CashSuper对象
        private CashSuper cs;

        public CashContext()
        {
        }

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

        internal void setBehavior(CashSuper cashSuper)
        {
            throw new NotImplementedException();
        }
    }

    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 - Math.Floor(money / moneyCondition) * moneyReturn;

            return result;
        }

    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        DataSet ds;//用于存放配置文件信息
        double total = 0.0d;//用于总计
        private void Form1_Load(object sender, EventArgs e)
        {
            //配置文件
            ds = new DataSet();
            ds.ReadXml(Application.StartupPath + "\\CashAcceptType.xml");
            //将读取到的记录绑定到下拉列表框中
            foreach (DataRowView dr in ds.Tables[0].DefaultView)
            {
                cbxType.Items.Add(dr["name"].ToString());
            }
            cbxType.SelectedIndex = 0;
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            CashContext cc = new CashContext();
            //根据用户的选项,查询用户选择项的相关行
            DataRow dr = ((DataRow[])ds.Tables[0].Select("name='" + cbxType.SelectedItem.ToString() + "'"))[0];
            //声明一个参数的对象数组
            object[] args = null;
            //若有参数,则将其分割成字符串数组,用于实例化时所用的参数
            if (dr["para"].ToString() != "")
                args = dr["para"].ToString().Split(',');
            //通过反射实例化出相应的算法对象
            cc.setBehavior((CashSuper)Assembly.Load("商场管理软件").CreateInstance("商场管理软件." + dr["class"].ToString(), false, BindingFlags.Default, null, args, null, null));

            double totalPrices = 0d;
            totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
            total = total + totalPrices;
            lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " " + cbxType.SelectedItem + " 合计:" + totalPrices.ToString());
            lblResult.Text = total.ToString();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            total = 0d;
            txtPrice.Text = "0.00";
            txtNum.Text = "1";
            lbxList.Items.Clear();
            lblResult.Text = "0.00";
        }
    }

  将 Strategy与Simple Factory 结合起来在使用, 这样做比单独用 Strategy 的好处是將switch判断从客户端移到了CashContext里,对客户端与业务逻辑层进行了解耦; 同时,Strategy模式又简化了客户端的调用,,从原来Simple Factory模式时必须认识两个类:工厂类和产品抽象类, 简化为只需要认识 CashContext 即可.。即使后续需要扩展收费方式,也不需要改动了客户端代码。

开闭原则

  对于扩展是开放的(Open for extension)。这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能。
  对于修改是关闭的(Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值