策略模式是指對一系列的算法定義,並將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立於使用它的客戶而獨立變化。
原文鏈接
優點:
- 策略模式利用組合、委託等技術和思想,可以避免很多if條件語句
- 策略模式提供了開放-封閉原則,使代碼更容易理解和拓展
簡單取值
很多例子以績效等級和薪資計算獎金爲說明
let calculateBouns = (level,salary)=>{
if(level=='A'){
return salary * 1.4;
}else if(level=='B'){
return salary * 1.3;
}else if(level=='C'){
return salary * 1.2;
}else{
return salary;
}
}
console.log(calculateBouns('A', 8000)); //11200
console.log(calculateBouns('C', 8000)); //9600
策略模式重構
//策略對象
class ruleA{
calculate(salary){
return salary * 1.4;
}
}
class ruleB{
calculate(salary){
return salary * 1.3;
}
}
class ruleC{
calculate(salary){
return salary * 1.2;
}
}
//獎金類
class Bouns{
constructor(){
this.salary = null;
this.level = null;
}
setLevel(level){
this.level = level;
}
setSalary(salary){
this.salary = salary;
}
getBouns(){
return this.level.calculate(this.salary);
}
}
let tom = new Bouns(),jerry = new Bouns();
//設置薪資
tom.setSalary(8000);
jerry.setSalary(10000);
//設置策略對象
tom.setLevel(new ruleA());
jerry.setLevel(new ruleA());
console.log(tom.getBouns()); //11200
console.log(jerry.getBouns()); //14000
jerry.setLevel(new ruleB());
console.log(jerry.getBouns()); //13000
表單
還有一種理解策略模式的例子就是表單驗證,通常會涉及到多個字段有效性判斷
let form = document.getElementById("Form");
form.onsubmit = function(){
if(form.username.value == ''){
alert('用戶名不能爲空');
return false;
}else if(form.username.value.length <= 6){
alert('用戶名長度不能小於6位');
return false;
}else if(form.password.value.length <= 6){
alert('密碼長度不能小於6位');
return false;
}else if(!/(^1[3|5|8][0-9]{9}$)/.test(form.phone.value)){
alert("手機號碼格式不正確");
return;
}else{
submit();
}
}
這樣實現的代碼的缺點:
- 函數體積臃腫,包含了很多if判斷
- 函數缺乏彈性,違反了開放-封閉原則
- 函數複用性差,如果增加表單需要類似驗證,只能複製一遍
策略模式實現表單驗證
// 策略對象
let strategys = {
isEmpty: (value,errorMsg)=> {
if(value === '') {
return errorMsg;
}
},
// 限制最小長度
minLength: (value,length,errorMsg)=> {
if(value.length < length) {
return errorMsg;
}
},
// 手機號碼格式
illegalPhone: (value,errorMsg)=> {
if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
return errorMsg;
}
}
};
class Validator{
constructor(){
this.cache = []; //保存校驗規則
}
addRule(dom,rules){
var self = this;
for(let i = 0, rule; rule = rules[i++]; ){
let strategyAry = rule.strategy.split(":");
let errorMsg = rule.errorMsg;
self.cache.push(function(){
let strategy = strategyAry.shift();
strategyAry.unshift(dom.value);
strategyAry.push(errorMsg);
return strategys[strategy].apply(dom,strategyAry);
});
}
}
check(){
for(let i = 0, fn; fn = this.cache[i++]; ) {
let msg = fn(); // 開始效驗 並取得效驗後的返回信息
if(msg) {
return msg;
}
}
}
}
// 代碼調用
let form = document.getElementById("Form");
let validateFunc = function(){
let validator = new Validator(); // 實例化Validator
//添加一些校驗規則
validator.addRule(form.username,[
{strategy: 'isEmpty',errorMsg:'用戶名不能爲空'},
{strategy: 'minLength:6',errorMsg:'用戶名長度不能小於6位'}
]);
validator.addRule(form.password,[
{strategy: 'minLength:6',errorMsg:'密碼長度不能小於6位'},
]);
validator.addRule(form.phone,[
{strategy: 'illegalPhone',errorMsg:'手機號格式不正確'},
]);
return validator.check();
};
form.onsubmit = function(){
let errorMsg = validateFunc();
if(errorMsg){
alert(errorMsg);
return false;
}else{
submit();
}
}
策略模式屬於對象行爲模式,主要針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,使得它們可以相互替換。