Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript之策略模式 #17

Open
Jouryjc opened this issue Aug 18, 2018 · 0 comments
Open

Javascript之策略模式 #17

Jouryjc opened this issue Aug 18, 2018 · 0 comments

Comments

@Jouryjc
Copy link
Owner

Jouryjc commented Aug 18, 2018

定义

策略模式的定义是定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

越狱相信大部分都看过,第一部剧中迈克尔设计了两条通往医务室的道路。国庆节、春节回家的方式很多种,我们可以选择飞机、高铁,还可以坐火车、大巴车。

作用

策略模式最主要的作用是在我们想找一种方式替换太多if else的条件语句,因为条件语句会让程序难以维护,且违反开放-封闭原则。

举例

根据模式的作用,我们来举例:

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

// test
calculateBonus('B', 20000);    // 40000
calculateBonus('A', 6000);    // 18000

上面的代码就是我们一开始说的,太多if else条件判断语句,且我们想增加第四种模式,比如'C'时,我们需要修改代码内部,添加如下代码:

if (performanceLevel === 'C') {
    return salary;
}

最后这个calculateBonus会多么庞大,想想就恶心。下面我们使用策略模式来重构一下代码,模式的目的就是讲算法的使用与算法的实现分离开来。

一个策略模式的程序至少由两部分组成。第一部分是一组策略类策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类context,Context接受客户的请求。随后把请求委托给某一个策略类。

var performanceS = function () {};

performanceS.prototype.calculate = function (salary) {
    return salary * 4;
};

var performanceA = function () {};

performanceS.prototype.calculate = function (salary) {
    return salary * 3;
};

var performanceB = function () {};

performanceS.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 (salary) {
    this.strategy  = strategy ;    // 设置员工绩效等级对应的策略对象
};

Bonus.prototype.getBonus = function () {    // 取得奖金数额
    return this.strategy.calculate(this.salary);    // 把计算奖金的操作委托给对应的策略对象
};

测试代码:

var bonus = new Bonus();

bonus.setSalary(10000);
bonus.setStrategy(new PerformanceS());

console.log(bonus.getBonus());    // 40000

bonus.setStrategy(new PerformanceA());
console.log(bonus.getBonus());    // 30000

上面的重构代码利用传统的OOP,在JS中,这个重构方式显得太笨拙了。函数也是对象,我们更直接和简洁的做法是把strategy直接定义为函数:

var strategies = {
    "S": function (salary) {
        return salary * 4;
    },
    "A": function (salary) {
         return salary * 3;
    },
    "B": function (salary) {
         return salary * 2;
    }
};

var calculateBonus = function (level, salary) {
    return strategies[level](salary);
};

console.log(calculateBonus('S', 20000));    // 80000
console.log(calculateBonus('A', 10000));    // 30000

策略模式在前端开发中更常见的使用时封装表单校验。

优点

  • 策略模式提供了对“开放-封闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法。
  • 策略模式提供了可以替换继承关系的办法。
  • 使用策略模式可以避免使用多重条件转移语句。

缺点

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

小结

本文通过提供接近传统面向对象语言的策略模式,也提供了更适合Javascript语言的策略模式版本。在Javascript语言的策略模式中,策略类往往被函数所替代,这时策略模式就成为一种“隐形”的模式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant