What is a policy model?
See Code Snippet 1 first.
// 代码片段1var bonus = new Bonus();bonus.setSalary(10000);bonus.setStrategy(new performanceS());console.log('bounsS' ,bonus.getBonus());// => 40000bonus.setStrategy(new performanceA());console.log('bounsA',bonus.getBonus());// => 30000
bonus
is an object, and the object comes with the context.
This object runs at different stages, by setStrategy
setting different parameters, resulting in bonus.getBonus()
different output results.
So the strategy pattern is to define a series of algorithms, encapsulate them each, and make them interchangeable.
The following code Snippet 2 is the definition of code fragment 1.
// 代码片段2var performanceS = function () { };performanceS.prototype.calculate = function (salary) { return salary * 4;};var performanceA = function () { };performanceA.prototype.calculate = function (salary) { return salary * 3;};var performanceB = function () { };performanceB.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); };
Improved policy mode
Similarly bonus.getBonus()
, the output results are different.
When the business becomes complex, this can cause code to be unpredictable.
Let's make a little improvement by having the object initialize and receiving a policy object, and setting the policy property is not modifiable.
// 代码片段3var bonusFactory = function(strategy){ this.salary = null; Object.defineProperty(this, 'strategy',{ value: strategy, writable: false, configurable:false, })};bonusFactory.prototype.setSalary = function (salary) { this.salary = salary; };bonusFactory.prototype.getBonus = function () { return this.strategy.calculate(this.salary); };var bonusS = new bonusFactory(new performanceS());bonusS.setSalary(10000);bonusS.strategy = 11;console.log('bonusS', bonusS.getBonus());var bonusA = new bonusFactory(new performanceA());bonusA.setSalary(10000);console.log('bonusA', bonusA.getBonus());
A functional approach to the strategy pattern
In this case, a ramda
functional tool library named is used.
var R = require('ramda');var salaryS = function(salary) { return salary * 4;};var salaryA = function(salary) { return salary * 3;};var salaryB = function(salary) { return salary * 2;};var getBonus = function(salary, strategy){ return strategy(salary); };var getBonusFacotry = R.curry(getBonus);var getBonusS = getBonusFacotry(R.__, salaryS);var getBonusA = getBonusFacotry(R.__, salaryA);var getBonusB = getBonusFacotry(R.__, salaryB);var getBouns1000 = getBonusFacotry(1000, R.__);console.log('封装奖金计算方式的策略');console.log(getBonusS(1000));console.log(getBonusA(1000));console.log(getBonusB(1000));console.log('封装奖金数目的策略');console.log(getBouns1000(salaryS));console.log(getBouns1000(salaryA));console.log(getBouns1000(salaryB));
You can see that the functional style is more flexible and concise.
JavaScript-shaped policy patterns