小看--策略模式

     (一)什么是策略模式

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

     (二)策略模式的演变

         场景,我们在做菜品促销的时候,通常都有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、上下文;

   

   (三)策略模式的优缺点

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

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

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

       

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

posted @ 2018-01-29 14:16  GDOUJKZZ  阅读(173)  评论(0编辑  收藏  举报