设计模式—策略模式

应用场景:现在超市需要一套超市收银系统,我们需要做一套收银系统出来。需求会很简单,我们一想,那不就是几个文本框的事吗,单价和数量输入,然后一算就好啦。但是,如果后期超市推出折扣活动,那我们这几个文本框还扛得住需求吗?这时候肯定有小伙伴儿说,加个下拉列表就行啦,那如果日后又有其他活动呢?岂不是要把代码改来改去喽?

这时候,就用到策略模式啦。

我用的是winform程序。

一:我们拟定现在有三种结算方式:无折扣,八折或者是满三百减一百。

分析一下,这三种折扣方式肯定需要三个类(基础策略类)来分别实现。然后我们再深入思考一下,既然他们三个的作用都是为了来满足不同的折扣运算,那我们是否可以将这三个类找一个共同点抽象出来呢?这时候就出现了抽象策略类(因为三个基础策略类只是为了实现活动需求的,但是超市经常会有各种活动,所以这些类就会被换来换去,这就是变化点,而封装变化点就是我们面向对象的一种很重要的思维方式)。

 

二:定义一个抽象策略类

抽象类就好比一个模具,你用A类实例化他,那他就是A实体,你用B类实例化他,那他就是B实体,但前提是A或者B两个类均继承过此抽象类并且进行了代码实现。

//抽象类是什么呢?其实就好比一个模具,你给他注入什么材质(类)他就变成什么材质(类)。
     public abstract class  CashSuper//抽象类,此类就是抽象策略类,折扣具体策略类均会继承(实现)此类
    {
        /// <summary>
        /// 入参为折扣前总金额,出参为折扣后金额
        /// </summary>
        /// <param name="Total"></param>
        /// <returns></returns>
        public abstract double CashFuncInterFace(double total);//抽象方法,此方法会在具体策略类继承(实现)抽象类后被实现。

    }

 三:既然抽象类已经有了,那我们就来创建不同的折扣类(基础策略类)来实现此抽象类吧。

public class CashFullPay : CashSuper//全额支付具体类
    {
        public override double CashFuncInterFace(double total)
        {
            return total;
        }
    }
public class CashEightDiscount : CashSuper//打八折的基础策略类
    {
        public override double CashFuncInterFace(double total)
        {
            return total * 0.8;
        }
    }
class CashThreeMinusOne : CashSuper//满300减100基础策略类
    {
        public override double CashFuncInterFace(double total)
        {
            return total - Math.Floor(total / 300) * 100;
        }
    }

四:此时,抽象策略类和三个基础策略类都分别建好了,但我们在哪里实例化抽象策略类呢?总不要在后台代码中吧?那样写的代码也太乱七八糟啦,所以我们给他一个统一的入口(上下文类:Context)

public class Context//上下文类,这个类的作用就是通过传入的参数,从而将抽象策略类(模型)实例化为各个基础策略类来满足场景需求
    {
        CashSuper cashSuper;//抽象策略类
        public Context(CashSuper cashSuper)//通过构造函数来实例化我们的抽象策略类
        {
            this.cashSuper = cashSuper;//通过构造函数中的基础策略类来实例化抽象策略类。就好比往模具中灌输不同的材质
        }

        //实例化的是什么基础策略类,这里返回的就是什么基础策略类所实现的方法
        public double CashFuncInterFace(double total)
        {
            return cashSuper.CashFuncInterFace(total);
        }
    }

五:实例化策略类的入口类也有啦,那我们就在后台代码中来根据不同的折扣来实例化不同的策略类吧。

private void btn_Confirm_Click(object sender, EventArgs e)
        {
            Context = null;
            double total = 0;
            switch (comBox_Mode.SelectedValue)
            {
                case "1":
                    Context = new Context(new CashFullPay());//无折扣
                    break;
                case "0.8":
                    Context = new Context(new CashEightDiscount());//八折
                    break;
                case "300-100":
                    Context = new Context(new CashThreeMinusOne());//满三百减一百
                    break;
                default://默认无折扣
                    Context = new Context(new CashFullPay());//无折扣
                    break;
            }
            total = Context.CashFuncInterFace(double.Parse(txt_Num.Text) * double.Parse(txt_Price.Text));//计算不同折扣后的金额
            txt_TotalInfo.Text += $"{txt_Name.Text}购买了{txt_Num.Text}个,每个{txt_Price.Text}元,优惠活动:{comBox_Mode.Text},共{total.ToString()}元\r\n";
            lab_TotalMoney.Text = (double.Parse(lab_TotalMoney.Text) + total).ToString();
        }

六:最后是效果图

 到这里,策略模式就算完事儿啦。但是细心的小伙伴一定发现了一个问题,那就是如果商场有新的活动,那我们就必须修改下拉列表并且在后端代码的switch中新增分支来满足需求,所以本质上我们还是得修改代码来重新编译,并没有解决实质性的问题。所以,这时候就又一次用到了我们上节提到的设计模式之一:简单工厂模式。这里如果运用简单工厂模式+策略模式就能完美地解决掉修改代码且重新编译的问题

具体实现方法,我们下节见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hero♞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值