一个策略模式的程序至少由两部分组成:定义:
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换
核心:
将算法的使用与算法的实现分离开来
①策略类,策略类中封装了具体的算法,并负责具体的计算过程
②环境类,环境类接收外部的请求,随后把请求委托给某一个策略类
实现策略模式
很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。例如,绩效为 S 的人年终奖有 4 倍工资,绩效为 A 的人年终奖有 3 倍工资,而绩效为 B 的人年终奖是 2 倍工资。假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖var S = function (salary) {
return salary * 4;
};
var A = function (salary) {
return salary * 3;
};
var B = function (salary) {
return salary * 2;
};
var calculateBonus = function (func, salary) {
return func(salary);
};
calculateBonus(S, 10000); // 输出:40000
这里将策略直接封装成函数,将封装的函数当作参数传递进calculateBonus函数中,当我们对这些函数发出“调用”的消息时,不同的函数会返回不同的执行结果
用策略模式来进行表单校验
<html>
<body>
<form action="http:// xxx.com/register" id="registerForm" method="post">
请输入用户名:<input type="text" name="userName"/>
请输入密码:<input type="text" name="password"/>
请输入手机号码:<input type="text" name="phoneNumber"/>
<button>提交</button>
</form>
</body>
</html>
// 定义策略类
var strategies = {
isNonEmpty: function (value, errorMsg) { // 不为空
if (value === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) { // 限制最小长度
if (value.length < length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) { // 手机号码格式
if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
return errorMsg;
}
}
};
// 定义环境类
var validataFunc = function () {
var validator = new Validator(); // 创建一个 validator 对象
// 使用validator来委托处理验证
/***************添加一些校验规则****************/
validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
validator.add(registerForm.password, 'minLength:6', '密码长度不能少于 6 位');
validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确');
var errorMsg = validator.start(); // 获得校验结果
return errorMsg; // 返回校验结果
}
var registerForm = document.getElementById('registerForm');
registerForm.onsubmit = function () {
var errorMsg = validataFunc(); // 如果 errorMsg 有确切的返回值,说明未通过校验
if (errorMsg) {
alert(errorMsg);
return false; // 阻止表单提交
}
};
// Validator 类
var Validator = function () {
this.cache = []; // 保存校验规则
};
Validator.prototype.add = function (dom, rule, errorMsg) {
var ary = rule.split(':'); // 把 strategy 和参数分开
this.cache.push(function () { // 把校验的步骤用空函数包装起来,并且放入 cache
var strategy = ary.shift(); // 用户挑选的 strategy
ary.unshift(dom.value); // 把 input 的 value 添加进参数列表
ary.push(errorMsg); // 把 errorMsg 添加进参数列表
return strategies[strategy].apply(dom, ary);
});
};
Validator.prototype.start = function () {
for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
var msg = validatorFunc(); // 开始校验,并取得校验后的返回信息
if (msg) { // 如果有确切的返回值,说明校验没有通过
return msg;
}
}
};
Vue高级异步组件+策略模式
context.vue<template>
<div>
<component :is="typeCom"/>
<button @click="next">下一个</button>
</div>
</template>
<script>
const TYPE = ["success", "warning", "info", "error"];
// 引入策略对象加载高级异步组件
import strategies from "@/strategies.js";
export default {
data() {
return {
status: 0,
};
},
computed: {
// 计算属性充当环境类
typeCom() {
let index = TYPE[this.status];
return strategies[index];
},
},
methods: {
next() {
if (this.status === TYPE.length - 1) {
this.status = 0;
} else {
this.status++;
}
},
},
};
</script>
strategies.js
const loading = {
template: '<div>加载中</div>'
}
const error = {
template: '<div>载错误</div>'
}
export default {
// 高级异步组件,参考-https://cn.vuejs.org/v2/guide/components-dynamic-async.html
success: () => ({
component: import('@/views/Success'),
loading,
error,
delay: 200,
timeout: 3000,
}),
warning: () => ({
component: import("@/views/Warning"),
loading,
error,
delay: 200,
timeout: 3000,
}),
info: () => ({
component: import("@/views/Info"),
loading,
error,
delay: 200,
timeout: 3000,
}),
error: () => ({
component: import("@/views/Error"),
loading,
error,
delay: 200,
timeout: 3000,
})
}
效果:
本来还想写个element表单验证的demo的,但是想了下,关于方法的策略模式在我们日常开发中的使用太多了,所以这里就不写了
参考
JavaScript设计模式与开发实践--曾探设计模式在vue中的应用(三)
Vue动态异步组件实现思路
其他参考: vue 异步组件与vue-router 懒加载实践
若有错误或者对于vue对于策略模式更好的实现欢迎在评论区留言,最后感谢阅读!!!
设计模式是对语言不足的补充
—— Peter Norvig
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!