zoukankan      html  css  js  c++  java
  • 小看--策略模式

         (一)什么是策略模式

              定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。(这个在目前看来是句废话),接下来,通过了解策略模式的应用场景,大家就会明白策略模式了。

         (二)策略模式的演变

             场景,我们在做菜品促销的时候,通常都有9折,8折,7折,或者联合打折。

     Console.WriteLine("........学习策略模式.........");
                double goodsPrice = 100.00;
                double discountPrice = 0.0; ;
                while (true){
                    Console.WriteLine("请输入商品折扣");
                    int discount =Convert.ToInt32(Console.ReadLine());
                    //假设有9折,8折,7折
                    switch (discount){
                        case 7:
                            //打七折的时候,要多加十块
                            discountPrice = goodsPrice * 0.7 + 10;
                            break;
                        case 8:
                            //打八折的时候,要多加十块
                            discountPrice = goodsPrice * 0.8 + 8;
                            break;
                        case 9:
                            //打七折的时候,要多加十块
                            discountPrice = goodsPrice * 0.9 + 5;
                            break;
                    }
                    Console.WriteLine($"打折后总价为:{discountPrice}");

           可能一开始,我们大部分同学都会像我上面这么干,用一个SwitchCase就搞定了不同折扣之间的关系,但是我们觉得我们这样做好不好呢,如果我们现在要增加一个打六折的东西,那又来改上端代码,这种做法呢,是属于面向过程的,完全没有体会到面向对象的思想,那么我们就应该多想一点,想深入一点,那该怎么做呢,可能有的同学就会想了,进行一个抽象(封装类,屏蔽细节)。

        所以接下来就有了我们这个版本的:

     while (true) {
                    Console.WriteLine("请输入商品折扣");
                    int discount = Convert.ToInt32(Console.ReadLine());
                    IStrategy gy = null;
                    //假设有9折,8折,7折
                    switch (discount) {
                        case 7:
                            //打七折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.7 + 10;
                            gy=new Seven();
                            break;
                        case 8:
                            //打八折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.8 + 8;
                            gy = new Eight();
                            break;
                        case 9:
                            //打七折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.9 + 5;
                            gy = new Night();
                            break;
                    }
                    Console.WriteLine($"打折后总价为:{gy.GetDiscountPrice(100)}");  //这个100是商品的原价
    
                }

          这个版本的改进:主要是我们把之前的打折的方法,都分别封装到类里面,然后实现了这些类都实现了IStratgy接口(如下图所示);,所以我们的代码改成了上面这个结构。

         

        到了这里,我们都要明白我们已经做到了开放抽象给上端了,上端是不依赖具体的细节了。

        我们继续,我们发现现在上端需要做的事情,1、接收用户的的输入选择相应的算法,2、执行相应的算法。

       

            在这里,我们这个例子中,执行算法,可能是比较简单一点,这里需要大家有点想像一下,我们实际中的,算法执行,可能非常复杂,可能需要进行写日志呀,根据不同的会员等级,对应的打折价格都是不一样的,很复杂。

    所以这里对于上端执行算法呢,我们要引入一个上下文(Context)。大家也可以延伸想一想,HttpContext:就是用来保存http的一些状态信息,Cookie,Session等等。我们这个上下文对象就是用来保存这次算法执行的一些初始化信息,中间变量,结果值等等(因为我们刚刚已经说,这个算法的执行是非常复杂的,需要做很多的准备)。

        public class DiscountContext
        {
            private readonly double _oldPrice;private readonly IStrategy _strategy;
            
    
            public DiscountContext(double oldPrice,IStrategy strategy){this._oldPrice = oldPrice;
                this._strategy = strategy;
            }
    
            public double Excute(){
                //很复杂的操作,不同操作系统,对应不同策略等等。
                Console.WriteLine("写日志");
                Console.WriteLine("做缓存");
                return this._strategy.GetDiscountPrice(this._oldPrice);
    
            }

          引入了这个类之后呢,我们上端也要进行修改一下;

      Console.WriteLine("请输入商品折扣");
                    int discount = Convert.ToInt32(Console.ReadLine());
                    IStrategy gy = null;
                    //假设有9折,8折,7折
                    switch (discount) {
                        case 7:
                            //打七折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.7 + 10;
                            gy=new Seven();
                            break;
                        case 8:
                            //打八折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.8 + 8;
                            gy = new Eight();
                            break;
                        case 9:
                            //打七折的时候,要多加十块
                            //discountPrice = goodsPrice * 0.9 + 5;
                            gy = new Night();
                            break;
                    }
                    var disContext=new DiscountContext(100,gy);
                    Console.WriteLine($"打折后总价为:{disContext.Excute()}");

        到此,我们的策略模式就结束了。下面来对上面进行一个总结:所谓的策略模式,首先要有很多策略(算法)先,才需要对所有策略,进行一个公共的抽取,让所有策略都继承自抽象;然后因为每个策略执行的复杂性以及诸多因素,我们需要把策略的执行过程,封装为一个上下文。策略模式的三要素:1、策略(有很多策略),2、策略的接口,3、上下文;

       

       (三)策略模式的优缺点

         优缺点,大家从上面应该是显而易见的了,优点:算法之间,可以自由转换。

         缺点:没一个算法类的复用性不高,增加了很多类。

      (四)策略模式和工厂模式结合

           

          由于时间关系,大家可以想想该怎么做。

  • 相关阅读:
    第22章 算法
    第二十一章 数据结构
    mysql 索引
    MySQL 视图
    MySQL 子查询
    MySQL 批量更新数据
    MySQL 默认值
    Spring 整体架构和环境搭建
    python之字符串
    python学习
  • 原文地址:https://www.cnblogs.com/gdouzz/p/8377076.html
Copyright © 2011-2022 走看看