title | date | tags | categories | ||
---|---|---|---|---|---|
策略模式 |
2020-05-07 |
|
|
::: warning 场景: 经常看斗鱼直播的朋友们可能会知道, 很多主播发起的抽奖活动都是有条件的, 比如带粉丝牌的, 点击关注的, 粉丝牌等级多少级以上才可以抽奖。现在 PDD 发起了一个抽奖但是需要粉丝牌等级 5 级,关注主播,并且粉丝的等级要 20 级以上的女用户才可以参与抽奖。那么这时候有的同学想这还不简单,唰唰唰的撸完了代码: :::
function checkAuth(data) {
if(data.fanCard < 5) {
return false;
}
if(!data.focus) {
return false;
}
if(data.grade < 20 ){
return false;
}
if(data.sex !== 'woman') {
return false;
}
...
}
那么这段代码又什么问题呢?我们来思考一下这个场景比如其他主播也有抽奖活动,但是要求不一样。比如大司马抽奖条件是只需要关注了即可抽奖。五五开抽奖条件是关注了并且是女观众就可以抽奖。那么如果继续用 if else 来整,那么岂不是很 low,很麻烦。因此这段代码就衍生出了以下问题:
- checkAuth 函数会 💥,会变得非常的庞大
- 策略项无法复用
- 违反开闭原则
那么我们如何解决这些问题呢?答案是策略模式:
// 定义策略
var strategies = {
checkFanCard: function(value) {
if (data.fanCard < 5) {
return false;
}
return true;
},
checkFocus: function(value) {
if (!data.focus) {
return false;
}
return true;
},
checkGrade: function(value) {
if (data.grade < 20) {
return false;
}
return true;
},
checkSex: function(value) {
if (data.sex !== 'woman') {
return false;
}
return true;
},
};
// 设置校验规则
var Validator = function() {
this.cache = [];
this.add = function(value, method) {
this.cache.push(() => strategies[method](value));
};
this.check = function() {
for (let index = 0; index < this.cache.length; index++) {
let validate = this.cache[index];
var data = validate();
if (!data) return false;
}
return true;
};
};
var DSM = function() {
var validator = new Validator();
var auth = {
focus: true,
};
validator.add(auth, 'checkFocus');
var check = validator.check();
return check;
};
var White = function() {
var validator = new Validator();
var auth = {
focus: true,
sex: 'woman'
};
validator.add(auth, 'checkFocus');
validator.add(auth, 'checkSex');
var check = validator.check();
return check;
};
什么时候可以用策略模式
::: tip
- 各个判断条件可以独立并且可以复用
- 策略需要灵活组合 :::