策略模式(Strategy)
将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定独立性,不会随客户端变化而变化。
策略对象
(需求:商场促销活动)
这种模式我们不需要关注内部的算法是什么,只需要关注最终返回的结果即可,类似状态模式
// 价格策略对象
var PriceStrategy = (function () {
// 内部算法对象
var stragtegy = {
// 100 返 30
return30(price) {
// parseInt可通过~~、|等运算符替换,要注意此时price要在[-2147483648,
// 2147483647]之间
// +price 转化为数字类型
return +price + parseInt(price / 100) * 30;
},
// 100 返 50
return50(price) {
return +price + parseInt(price / 100) * 50;
},
// 9 折
percent90(price) {
// JavaScript 在处理小数乘除法有bug,故运算前转化为整数
return price * 100 * 90 / 10000;
},
// 8 折
parcent80(price) {
return price * 100 * 80 / 10000;
},
// 5 折
percent50(price) {
return price * 100 * 50 / 10000;
}
}
// 策略算法调用接口
return function (algorithm, price) {
// 如果算法存在,则调用算法,否则返回false
return stragtegy[algorithm] && stragtegy[algorithm](price)
}
}());
let price = PriceStrategy('percent50', 100);
console.log(price); // 50
缓冲函数
(jq中的策略模式
)
<div class="box1" style="height: 100px;background-color: red;"></div>
<div class="box2" style="height: 100px;background-color: greenyellow"></div>
<div class="box2" style="height: 100px;background-color: blue;"></div>
<div class="box2" style="height: 100px;background-color: yellow;"></div>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js"></script>
<script>
$('.box1').animate({
width: '200px' }, 5000, 'linear');
$('.box2').animate({
width: '200px' }, 5000, 'swing');
$('.box3').animate({
width: '200px' }, 5000, 'easeOutQuart');
$('.box4').animate({
width: '200px' }, 5000, 'easeOutBounce');
</script>
表单验证
策略模式的表单示例
// 表单正则验证策略对象
var InputStrategy = (function () {
var strategy = {
// 是否为空
notNull(value) {
return /\s+/.test(value) ? '请输入内容' : '正确';
},
// 是否是一个数字
number(value) {
return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '正确' : '请输入数字';
},
// 是否是本地电话
phone(value) {
return /^\d{3}\-\d{8}$|^\d{4}\-\d{7}$/.test(value) ? '正确' : `请输入正
确的电话号码格式, 如: 010-12345678 或 0418-1234567`;
}
}
return {
// 验证接口 type 算法 value 表单值
check(type, value) {
// 去除收尾空白符
value = value.replace(/^\s+|\s+$/g, '');
return strategy[type] ? strategy[type](value) : '没有该类型的检测方法'
},
// 添加策略
addStrategy(type, fn) {
strategy[type] = fn;
}
}
}());
InputStrategy.check('number', '1234'); // '正确'
InputStrategy.check('number', '123a4'); // '请输入数字'
InputStrategy.check('username', 'Lee'); // '没有该类型的检测方法'
InputStrategy.addStrategy('username', function (value) {
return value.length <= 3 ? '正确' : '用户名不得大于3个字符';
});
InputStrategy.check('username', 'Lee'); // '正确'
InputStrategy.check('username', 'PLee'); // '用户名不得大于3个字符'
特点:
策略模式
的优点
:策略模式
封装了一组代码簇,并且封装的代码相互之间独立
,便于对算法的重复引用
,提高了算法的复用率
。策略模式
与继承相比
,在类的继承
中当需求很多算法时
,就不得不创建出多种类
,这样会导致算法与算法的使用者耦合在一起
,不利于算法的独立演化
,并且在类的外部改变类的算法难度也是极大的
。- 同状态模式一样,
策略模式
也是一种优化分支判断语句的模式
,采用策略模式
对算法封装
使得算法
更利于维护
。
策略模式
的缺点
:- 由于选择哪种算法的决定权在用户,所以对用户来说就必须了解每种算法的实现。这就
增加了用户对策略对象的使用成本
。其次,由于每种算法间相互独立
,这样对于一些复杂的算法处理相同逻辑的部分无法实现共享
,这就会造成一些资源的浪费
。当然你可以通过享元模式来解决
。
- 由于选择哪种算法的决定权在用户,所以对用户来说就必须了解每种算法的实现。这就