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

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、使用策略模式重构代码

扫描二维码关注公众号,回复: 474529 查看本文章

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

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

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

// 策略类
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,并且知道他们之间的不同点,这是违反最少知识原则的。

猜你喜欢

转载自blog.csdn.net/lihangxiaoji/article/details/79911217