Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

策略模式 #17

Open
isNeilLin opened this issue Nov 30, 2017 · 0 comments
Open

策略模式 #17

isNeilLin opened this issue Nov 30, 2017 · 0 comments
Labels
设计模式 设计模式相关

Comments

@isNeilLin
Copy link
Owner

策略模式

定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

并且使它们可以相互替换”,这句话在很大程度上是相对于静态类型语言而言的。因为静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。当它们的真正类型被隐藏在接口后面时,它们才能被相互替换。而在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>
@isNeilLin isNeilLin added 设计模式 设计模式相关 and removed 读书笔记 labels Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
设计模式 设计模式相关
Projects
None yet
Development

No branches or pull requests

1 participant