定义:定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。
解决的问题:在多重算法相似的情况下,使用if...else或单纯使用硬编码方式导致新增一种方法都需要修改封装算法类的源代码,更换查找方法也需要修改客户端调用的代码,维护较为困难。
何时使用:系统中有许多类,而区分它们的只是它们的直接行为,算法需要自由切换。
如何实现:将这些算法封装成一个一个的类,任意地替换。
优点:算法可以自由切换;消除了一些if...else语句 扩展性良好;增加一个策略只需要实现接口。
缺点:策略类会增多;所有策略类都需要对外暴露;通信开销大,耦合度高。
示例:使用策略模式来实现表单验证
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>策略模式</title>
</head>
<body>
<form action="xxx.com" method="post" id="registerForm">
请输入用户名:<input type="text" name="userName">
请输入密码:<input type="password" name="password">
请输入手机号码:<input type="text" name="phoneNumber">
<button>提交</button>
</form>
<script>
var registerForm = document.getElementById('registerForm')
// 使用策略模式封装
var strategies = {
isNonEmpty: function (value, errorMsg) {
if (value == '') {
return errorMsg
}
},
minLength: function (value, length, errorMsg) {
if (value.length < 6) {
return errorMsg
}
},
isMobile: function (value, errorMsg) {
if (!/^1[3|5|8][0-9]{9}$/.test(value)) {
return errorMsg
}
}
}
//假设有一个验证类 Validator new Validator()
var validateFun = function () {
var validator = new Validator()
//添加验证规则
validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空')
validator.add(registerForm.password, 'minLength:6', '密码不能小于6位')
validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确')
//开启验证
var errorMsg = validator.start()
return errorMsg
}
registerForm.onsubmit = function () {
var errorMsg = validateFun()
if (errorMsg) {
alert(errorMsg)
return false
}
}
//封装策略类
var Validator = function () {
//保存验证规则的数组
this.cache = []
}
Validator.prototype.add = function (dom, rule, errorMsg) {
var ary = rule.split(':')
this.cache.push(function () {
var strategy = ary.shift() //弹出用户选择的验证规则
ary.unshift(dom.value) //把dom的值放在首位
ary.push(errorMsg)
//ES5写法 return strategies[strategy].apply(dom, ary)
return strategies[strategy](...ary)
})
}
Validator.prototype.start = function () {
for (var i = 0, vaFunc; vaFunc = this.cache[i++];) {
var msg = vaFunc()
if (msg) {
return msg
}
}
}
</script>
</body>
</html>
以上仅作为个人学习笔记。