• 策略


      策略,Strategy,古时也称“计”,为了达成某个目标的方案,目标不同,方案也随之更改。例如特工执行任务时总要准备好几套方案以应对突如其来的变化,A计划实施过程中情况突变导致预案无法继续实施,则马上更换为B计划,正所谓计划不如变化快,提前策划固然非常重要,而随机应变更是不可或缺,只有保证这种可变的灵活性才能立于不败之地。世界永远都在变,唯一不变的就是变本身。

      作为有思想的码农,我们当然也不能把程序写死了,一个设计优秀的系统,绝不是把现有类的代码改来改去,而一定是扩展类并接入系统,这样马上就能适应不同的用户需求。

      就拿游戏机来举个例子,早期的俄罗斯方块风靡全球,后来国内流行一种掌机,只能玩俄罗斯方块这一个游戏,可过不了多久大家就玩腻了,于是热度降低这种游戏机很快就退出市场了,显然这是一种失败的设计模式。

      后来任天堂出品的Game Boy以及Sony的PSP则完全带来了不同的用户体验,系统提供了统一的卡槽接口,玩家只要更换卡带或MD就可以达到更换游戏的目的,做到了一机多用。

    各种游戏卡带,更换游戏方便多了。

      好了,开始实战部分,为了说明问题,我们继续发扬极简主义的优良传统,我们就做一个最简单的计算器好了,假设我们的计算器只能进行加减法,代码如下。

    public class Calculator {//违反设计模式原则的做法
        public int add(int a, int b){//加法
            return a + b;
        }
    
        public int sub(int a, int b){//减法
            return a - b;
        }
    }

      这样写ok吗?我们往后的扩展想想,如果随着我们的算法不断增加,如乘法、除法、次方、开方等等,那么这个计算器类就得不断的改啊改啊,每次升级算法我们都要把机器给拆开然后更改类代码,这岂不是作死?改到最后这个庞大的系统会不会变化这样?

      或者是……如这般疯狂?

      作死!的确是作死!我们来换个思路,先思考一下,既然不能把算法给写死在这里面,那一定要把这个算法给抽象一下,把实现细节从这个类里抽离出来,独立出来成为n个策略,就当下来讲我们一共有俩个策略,一个是加法策略,一个是减法策略,他们实现的都是同一个算法接口,接收参数为操作数a,以及被操作数b。

    public interface Strategy {//算法标准
        public int calculate(int a, int b);//操作数,被操作数
    }

    下来实现加法策略、减法策略。

    public class Addition implements Strategy{//实现算法接口
    
        @Override
        public int calculate(int a, int b) {//加数与被加数
            return a + b;//这里我们做加法运算
        }
    
    }
    public class Subtraction implements Strategy{//实现算法接口
    
        @Override
        public int calculate(int a, int b) {//减数与被减数
            return a - b;//这里我们做减法运算
        }
    
    }

    算法写好了,开始写计算器。

     public class Calculator {//计算器类
         private Strategy strategy;//拥有某种算法策略
     
         public void setStrategy(Strategy strategy) {//接入算法策略
             this.strategy = strategy;
         }
     
         public int getResult(int a, int b){
             return this.strategy.calculate(a, b);//返回具体策略的结果
        }
    }

    可以看到,计算器类里已经把之前的具体加减算法实现代码给剥离出去了,要用哪个算法,只需要注入进来,然后获得计算结果getResult实际上调用的是具体算法的calculate,我们来看怎样使用这个计算器。

     public class Client {
         public static void main(String[] args) {
             Calculator calculator = new Calculator();//实例化计算器
             calculator.setStrategy(new Addition());//接入加法实现
             int result = calculator.getResult(1, 1);//计算!
             System.out.println(result);//得到的是加法结果2
     
             calculator.setStrategy(new Subtraction());//再次接入减法实现
             result = calculator.getResult(1, 1);//计算!
            System.out.println(result);//得到的是减法结果0
    
        }
    }

    注释已经写得非常明白了,相信大家都看懂了吧。那么我们这个计算器可以说是具有算法策略扩展性的,以后要有新的算法是不需要再更改任何现有代码的,只需要新写一个算法比如乘法Multiplication,并实现calculate方法,接下来要做的只是组装上去便可以使用了。

      从以上的几个例子可以看出,我们的策略模式获得了极大的应用,策略实现类已经成为独立于宿主之外的模块,即插即用。可以组合成为一个整体,又可以分拆独立,可以发生关联,但绝不耦合,既对立又统一,这是唯物辩证法的绝佳体现。

    总结:

      策略模式注重行为的的抽象,若我们直接实现计算器类时,直接将加、减、乘、除等方法,写死在里面,若后续计算器类还想再增加求平方的方法,这时就需要去修改计算器这个实现类,违反了软件设计的开闭原则。而如果我们利用面向结构编程,将计算器中的算法抽象出来,然后用哪个算法去计算结果,就将这个算法的实现类注入到计算器类中,这样就大大保证了程序的可扩展性。其中,计算器类中,对算法的set方法,参数就用多态定义,即可。

  • 相关阅读:
    在CentOS 6上安装Apache和PHP
    花10分钟看一看,少走30年的弯路
    IOS开发之UITabBarController与UINavigationController混合使用
    重构tableview!
    初学IOS之TableView
    关于mac下配置mysql心得
    类,对象,方法的
    shell脚本
    关于我
    机器学习&深度学习视频资料汇总
  • 原文地址:https://www.cnblogs.com/guoyu1/p/13803319.html
Copyright © 2020-2023  润新知