设计模式-策略模式结合简单工厂

前言:
策略模式可以定义一系列的算法,并且根据需求选择算法。算法之间还可以相互替换,不影响客户端的使用。
需求:
还是以商场的收银系统为例,这次添加一个需求。在上一个需求上加一个,打5折和打7折的需求。
类图:
在这里插入图片描述
实现:
抽象策略类(没有具体的实现策略,而是把具体策略的共同方法抽象到里面)

/// <summary>
    /// 现金收费的抽象类,父类。
    /// </summary>
    abstract class CashSuper
    {
        /// <summary>
        /// 现金收费的抽象方法
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>当前价格</returns>
        public abstract double acceptCash(double money);
    }//end CashSuper

正常收费策略(继承抽象策略类)

 /// <summary>
     /// 正常收费子类
     /// </summary>
    class CashNormal : CashSuper
    {
        /// <summary>
        /// 重写父类的收费方法
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>当前价格</returns>
        public override double acceptCash(double money)
        {
            return money;//原价返回
        }//end acceptCash
    }//end CashNormal

打折策略(继承抽象策略类)

/// <summary>
    /// 打折收费子类
    /// </summary>
    class CashRedbate : CashSuper
    {
        private double moneyRebate = 1d;//具体打几折
        /// <summary>
        /// 获取具体打几折
        /// </summary>
        /// <param name="moneyRebate">具体打几折</param>
        public CashRedbate(string moneyRebate)
        {
            this.moneyRebate = double.Parse(moneyRebate);
        }//end CashRedbate
        /// <summary>
        ///打折的方法
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>打折之后的价格</returns>
        public override double acceptCash(double money)
        {
            //原价*具体打折数=打折之后的价格
            return money * moneyRebate;
        }//end aceptCash
    }//end CashRedbate

返利策略(继承抽象策略类)

    /// <summary>
    /// 返利收费子类
    /// </summary>
    class CashReturn : CashSuper
    {
        private double moneyCondition = 0.0d;//返利条件
        private double moneyReturn = 0.0d;//反多少
        /// <summary>
        /// 返利条件初始化
        /// </summary>
        /// <param name="moneyCondition">返利条件</param>
        /// <param name="moneyReturn">反多少</param>
        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);//返利条件
            this.moneyReturn = double.Parse(moneyReturn);//反多少
        }//end CashRetur
        /// <summary>
        /// 返利计算方法
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>返利之后的价格</returns>
        public override double acceptCash(double money)
        {
            double result = money;//要返回的价格
            //判断是否满足返利的要求
            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;

            }//end if
            return result;//返回价格
        }//end AcceptCash
    }//end CashReturn

客户端(在客户端用switch选择具体的策略,把选好的具体策略传入CashFactoury里面。然后根据传进去的策略进行具体的计算。)

             double total = 0.0d;
        private void butok_Click(object sender, EventArgs e)
        {
             CashContext cc = null;//实例化策略模式
            //根据条件选择策略
             switch (cbxType.Selecteditem.Tostring())
            {
                case "正常收费":
                    cc = new CashNormal();
                    break;
                case "满300返100":
                    cc = new CashReturn("300", "100");
                    break;
                case "打8折":
                    cc = new CashRedbate("0.8");
                    break;
                case "打5折":
                    cc = new CashRedbate("0.5");
                    break;
                case "打7折":
                    cc = new CashRedbate("0.7");
                    break;
            }//end switch
            
            double totalprices = 0d;//金额
            totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
                *Convert.ToDouble(txtNumber2.Text));
            //累加
            total = total + totalprices;
            listBox1.Items.Add("单价:" + txtNumber1.Text + "数量:" + txtNumber2.Text + "\t" +
           combType.SelectedItem + "合计:" + totalprices.ToString());
            lblmony.Text = total.ToString();
        }
        }//end createCashAccept

反思:
在第一个简单工厂模式我们就把客户端的判断部分移动到了后端,但是在策略模式这里我们又把判断部分移到了客户端。让客户端来选择具体使用哪个策略。
解决方案:
我们可以把策略模式和简单工厂模式结合使用,这样即解决了算法可以灵活替换还把选择部分又移动到了后端。
策略模式+简单工厂模式:(只需要修改原来的CashFactory类和客户端代码)
CashFactory类

 class CashFactory
    {
        CashSuper cs = null;//实例化父类
        /// <summary>
        /// 根据需要实例化对象
        /// </summary>
        /// <param name="type">需要实例化的对象名</param>
        /// <returns>返回实例化之后的对象</returns>
        public  CashFactory(string type)
        {
            //判断选择了哪种优惠方案
            switch (type)
            {
                case "正常收费":
                    cs = new CashNormal();
                    break;
                case "满300返100":
                    cs = new CashReturn("300", "100");
                    break;
                case "打8折":
                    cs = new CashRedbate("0.8");
                    break;
                case "打5折":
                    cs = new CashRedbate("0.5");
                    break;
                case "打7折":
                    cs = new CashRedbate("0.7");
                    break;
            }//end switch
             
        }//end createCashAccept
        /// <summary>
        /// 根据具体实例化对象,调用方法。
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>当前价格</returns>
        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }//end GetResult
    }//end class CashFactory

客户端(修改之后的)

       double total = 0.0d;
        private void butok_Click(object sender, EventArgs e)
        {
        //实例化策略工厂类
            CashFactory cc = new CashFactory(combType.SelectedItem.ToString());
            double totalprices = 0d;//金额
            totalprices = cc.GetResult(Convert.ToDouble(txtNumber1.Text )
                *Convert.ToDouble(txtNumber2.Text));
            //累加
            total = total + totalprices;
            listBox1.Items.Add("单价:" + txtNumber1.Text + "数量:" + txtNumber2.Text + "\t" +
           combType.SelectedItem + "合计:" + totalprices.ToString());
            lblmony.Text = total.ToString();
        }

结果:
在这里插入图片描述

posted @ 2019-11-07 17:12  康世行  阅读(88)  评论(0编辑  收藏  举报