·  阅读 3956

策略模式

策略模式应用

最初代码

``````var calculateBouns = function (performanceLevel, salary) {
if (performanceLevel === 'S') {
return salary * 4;
}

if (performanceLevel === 'A') {
return salary * 3;
}

if (performanceLevel === 'B') {
return salary * 2;
}
}

calculateBouns('S', 20000);

• 包含过多的`if-else`语句;
• 可扩展性较差，如果我们需要扩展一个新的绩效C，就需要深入到`calculateBouns`内部实现，违反了开闭原则;
• 算法复用性差，如果需要复用这段算法，只能选择复制黏贴

使用策略模式重构代码

``````// 绩效算法
var 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 Bouns = function() {
this.salary = null; // 原始工资
this.strategy = null; // 绩效等级对应的策略对象
}

Bouns.prototype.setSalary = function(salary) {
this.salary = salary;
}
Bouns.prototype.setStrategy = function(strategy) {
this.strategy = strategy;
}
Bouns.prototype.getBouns = function() {
return this.strategy.calculate(this.salary);
}

var bouns = new Bouns()
bouns.setSalary(1000); // 设置工资
bouns.setStrategy(new performanceS()); // 设置绩效
bouns.getBouns(); // 获取奖金

JavaScript版本的策略模式

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

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

calculateBouns('A', 2000);

源码中的策略模式

Axios

``````// lib/defaults.js

if (typeof XMLHttpRequest !== 'undefined') {
// For browsers use XHR adapter
} else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
// For node use HTTP adapter
}
}

``````// lib/adapters/xhr.js

return new Promise((resolve, reject) => {
/**
省略xxxx代码
*/
var request = new XMLHttpRequest();

/**
省略xxxx代码
*/
request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
})

/**
省略xxxx代码
*/

// 对response进行校验，满足条件则请求成功 resolve(response)
settle(resolve, reject, response);
}
}

return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
var resolve = function resolve(value) {
resolvePromise(value);
};
var reject = function reject(value) {
rejectPromise(value);
};

/**
省略xxxx代码
*/
var transport;
// 源码中有不同逻辑的判断，这里简化为其中一种情况
transport = isHttpsProxy ? https : http;

/**
省略xxxx代码
*/

var req = transport.request(options, function handleResponse(res) {
/**
省略xxxx代码
*/
res.on('end', function handleStreamEnd() {
/**
省略xxxx代码
*/
settle(resolve, reject, response);
});
})
})
}

策略模式应用

``````class VIPClient {
constructor(clientId) {
this.clientId = clientId;
}

getList() {
// 获取列表接口
return getVIPList(this.id)
}

getDetail() {
// 获取详情接口
return getVIPDetail(this.id)
}
}

class Client {
constructor(clientId) {
this.clientId = clientId;
}

getList() {
// 获取列表接口
return getList(this.id)
}

getDetail() {
// 获取详情接口
return getDetail(this.id)
}
}

let client;
if (vip) {
client = new VIPClient(id)
} else {
client = new Client(id)
}

// 获取列表
const list = await client.getList()