美文网首页我爱编程
JavaScript设计模式三(策略模式)

JavaScript设计模式三(策略模式)

作者: moyi_gg | 来源:发表于2018-04-16 14:21 被阅读0次

    JavaScript设计模式三(策略模式)

    策略模式定义

    定义一系列算法,把他们一个个封装起来,并且使他们相互替换

    我们可以先看一个例子

    策略模式计算年终奖

    大家知道年终奖的发放是和工资基数和年终考评来计算的,例如A是4个月工资,B是3个月工资,C是2个月工资。

    1、最初的代码实现

    var calculateBonus = function(level, salary) {
        if (level === 'A') {
            return salary*4;
        }
        
        if (level === 'B') {
            return salary*3;
        }
        
        if (level === 'C') {
            return salary*2;
        }
    }
    

    使用方法:
    calcaluteBonus('B', 10000)

    这段代码平常我们见到的很多,但是它有着明显的缺点

    • 函数很杂,随着业务逻辑的增加,这个函数会越来越大
    • 缺乏弹性,例如我们A的考评变成5倍,或者增加D的考评,必须要去修改这个函数,这里是违反了开发-封闭原则
    • 算法不存在复用性,例如我们需要再另外一个函数中使用这些算法,需要重新再写一遍

    2、利用组合函数重构代码

    简单来解释,就是把那些算法封装到一个个函数里面。

    
    var algorithmA = function(salary) {
        return salary*4;
    }
    
    var algorithmB = function(salary) {
        return salary*3;
    }
    
    var algorithmC = funtion(salary) {
        return salary*2;
    }
    
    var calculateBonus = function(level, salary) {
        if (level === 'A') {
            return algorithmA(salary);
        }
        
        if (level === 'B') {
            return algorithmB(salary*3);
        }
        
        if (level === 'C') {
            return algorithmC(salary*2);
        }
    }
    

    这么修改之后,这些算法我们可以在其他函数里面复用了,但是还是没有解决calculateBonus函数庞大的问题。

    3、使用策略模式重构代码

    一个策略模式的程序至少由两部分组成

    • 一组策略类,也就是算法,这些策略类会封装算法,并且负责具体的计算规则
    • 环境上下文,接受客户的请求,然后把请求委托给某一个策略类。因此在这个上下文中要维持对某一个策略对象的引用。

    我们先看一个模仿面向对象语言的实现:

    // 策略类
    var algorithmA = function(){}
    
    algorithmA.prototype.calculate = function(salary) {
        return salary*4;
    }
    
    var algorithmB = function(){}
    
    algorithmB.prototype.calculate = function(salary) {
        return salary*3;
    }
    
    var algorithmB = function(){}
    
    algorithmB.prototype.calculate = function(salary) {
        return salary*2;
    }
    
    // 环境上下文
    
    var Bonus = function(){
        this.salary = null;
        this.strategy = null;
    }
    
    Bonus.prototype.setSalary = function(salary) {
        this.salary = salary;
    }
    
    Bonus.prototype.setStrategy = function(strategy) {
        this.strategy = strategy;
    }
    
    Bonus.prototype.getBonus = function() {
        return this.strategy.calculate( this.salary );
    }
    
    // 使用
    
    var bonus = new Bonus();
    
    bonus.setSalary(10000);
    bonus.setStrategy(new algorithmA());
    
    console.log(bonus.getBonus());
    

    刚才上面说到了面向对象的的实现,但是其实我们很少会这样写,我们看看JavaScript的版本

    4、JavaScript版本的策略模式

    var strategies = {
        "A": function(salary) {
            return salary*4;
        },
        "B": function(salary) {
            return salary*3;
        },
        "C": function(salary) {
            return salary*2;
        },
    };
    
    var calculateBonus = function(level, salary) {
        return strategies[level](salary);
    };
    
    calculateBonus('A', 10000);
    

    惊不惊喜,意不意外,就是这么简单。

    策略模式更加广义的用法

    上面我们说的策略模式封装的是算法,但是实际上我们不仅仅可以封装算法,还可以封装一些业务规则,例如表单验证里面,我们可以封装不同的校验逻辑,这里就不举例说明了,如果有兴趣可以参考JavaScript设计模式与实践这本书

    策略模式的优缺点

    优点:

    • 策略模式利用组合、委托和多态的技术和思想,能够有效的避免多重条件选择语句
    • 策略模式符合开发-封闭原则,把算法封装在独立的strategy中,让算法利于切换、理解和扩展
    • 策略模式的算法能够很方便的在其他地方复用
    • 策略模式利用组合和委托让环境上下文有执行算法的能力,这也是继承的一种体现

    缺点:

    • 策略模式需要在代码中增加许多策略类或者策略对象
    • 要使用好策略模式的前提是:必须了解所有的strategy,并且知道他们之间的不同点,这是违反最少知识原则的。

    相关文章

      网友评论

        本文标题:JavaScript设计模式三(策略模式)

        本文链接:https://www.haomeiwen.com/subject/tucekftx.html