Open
Description
策略模式
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
并且使它们可以相互替换”,这句话在很大程度上是相对于静态类型语言而言的。因为静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。当它们的真正类型被隐藏在接口后面时,它们才能被相互替换。而在JavaScript这种“类型模糊”的语言中没有这种困扰,任何对象都可以被替换使用。因此,JavaScript中的“可以相互替换使用”表现为它们具有相同的目标和意图。
策略模式的目的就是将算法的使用与算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。 第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明Context中要维持对某个策略对象的引用
// JavaScript版本的策略模式
var strategies = {
'S': function(salary){
return salary * 4;
},
'A': function(salary){
return salary * 3;
},
'B': function(salary){
return salary * 2;
}
}
var calculate = function(level, salary){
return strategies[level](salary);
}
缓动动画
/*
@param {
t: 动画已消耗的时间,
b: 小球原始位置,
c: 小球目标位置,
d: 动画持续的总时间
}
*/
var tween = {
linear: function(t, b, c, d){
return c*t/d + b;
},
easeIn: function(t, b, c, d){
return c * ( t /= d # 策略模式
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
> 并且使它们可以相互替换”,这句话在很大程度上是相对于静态类型语言而言的。因为静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。当它们的真正类型被隐藏在接口后面时,它们才能被相互替换。而在JavaScript这种“类型模糊”的语言中没有这种困扰,任何对象都可以被替换使用。因此,JavaScript中的“可以相互替换使用”表现为它们具有相同的目标和意图。
策略模式的目的就是将算法的使用与算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。 第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明Context中要维持对某个策略对象的引用
```javascript
// JavaScript版本的策略模式
var strategies = {
'S': function(salary){
return salary * 4;
},
'A': function(salary){
return salary * 3;
},
'B': function(salary){
return salary * 2;
}
}
var calculate = function(level, salary){
return strategies[level](salary);
}
缓动动画
/*
@param {
t: 动画已消耗的时间,
b: 小球原始位置,
c: 小球目标位置,
d: 动画持续的总时间
}
) * t + b;
},
strongEaseIn: function(t, b, c, d){
return c * ( t /= d ) * t * t * t * t + b;
},
strongEaseOut: function(t, b, c, d){
return c * ( ( t = t / d - 1) * t * t * t * t + 1 ) + b;
},
sineaseIn: function( t, b, c, d ){
return c * ( t /= d) * t * t + b;
},
sineaseOut: function(t,b,c,d){
return c * ( ( t = t / d - 1) * t * t + 1 ) + b;
}
}
var Animate = function(dom){
this.dom = dom;
this.startTime = 0;
this.startPos = 0;
this.endPos = 0;
this.easing = null;
this.duration = null;
this.prototyName = null;
}
Animate.prototype.start = function(prototyName,endPos,duration,easing){
this.startTime = +new Date;
this.startPos = this.dom.getBoundingClientRect()[prototyName];
this.prototyName = prototyName;
this.endPos = endPos;
this.duration = duration;
this.easing = tween[easing]; // 缓动算法
var self = this;
var timeId = setInterval(function(){
if(self.step()===false){
clearInterval(timeId);
}
})
}
Animate.prototype.step = function(){
var t = +new Date;
if(t >= this.startTime+this.duration){
this.update(this.endPos);
return false;
}
var pos = this.easing(t-this.startTime, this.startPos, this.endPos - this.startPos, this.duration)
this.update(pos);
}
Animate.prototype.update = function(pos){
this.dom.style[this.prototyName] = pos + 'px';
}
var div = document.getElementById( 'div' );
var animate = new Animate( div );
animate.start( 'left', 500, 1000, 'strongEaseOut' );
表单验证
<body>
<form id="registerForm">
请输入用户名:<input type="text" name="userName"/ >
<br>
请输入密码:<input type="text" name="password"/ >
<br>
请输入手机号码:<input type="text" name="phoneNumber"/ >
<br>
<button>提交</button>
</form>
<script type="text/javascript">
// 表单校验
var strategies = {
isEmpty: function(val,errormsg){
if(val===''){
return errormsg;
}
},
minLength: function(val,length,errormsg){
if(val.length < length){
return errormsg;
}
},
isMobile: function(val,errormsg){
if(!/(^1[3|5|8][0-9]{9}$)/.test(val)){
return errormsg;
}
}
}
var Validator = function(){
this.cache = [];
}
Validator.prototype.add = function(dom, rule, msg){
var ary;
if(arguments.length===3){
ary = rule.split(':');
var strategy = strategies[ary.shift()];
ary.unshift(dom.value);
ary.push(msg);
this.cache.push(function(){
return strategy.apply(this,ary);
})
}else if(arguments.length===2&&(Object.prototype.toString.call(rule)==='[object Array]')){
rule.map(ruleObj=>{
this.add(dom,ruleObj.strategy,ruleObj.errormsg);
})
}
}
Validator.prototype.start = function(){
for(var i=0, func;func = this.cache[i++]; ){
var msg = func();
if(msg){
return msg;
}
}
}
var ValidatorFuc = function(){
var validator = new Validator();
validator.add(registerForm.userName,[
{
strategy: 'isEmpty',
errormsg: '用户名不能为空'
},
{
strategy: 'minLength:8',
errormsg: '用户名长度不能少于8位'
}
]);
validator.add(registerForm.password,'minLength:6','密码长度不能少于6位');
validator.add(registerForm.userName,'isMobile','手机号格式不正确');
var errormsg = validator.start();
return errormsg;
}
document.getElementById('registerForm').onsubmit = function(e){
e.preventDefault();
var errorMsg = ValidatorFuc(); // 如果errorMsg有确切的返回值,说明未通过校验
if ( errorMsg ){
alert ( errorMsg );
return false; // 阻止表单提交
}
}
</script>