策略模式学习笔记

平时我们在写代码时会偶尔用到策略模式的思想,但我们却不自知。今天学习了策略模式,特记录如下:

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

策略模式的目的是:将算法的使用和实现分离开来。一个基于策略模式的程序至少由两部分组成。第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类,Context要维持对某个策略对象的引用。

在开发项目时,肯定离不开表单检验这一个环节。

在编写一个注册页面时,在点击注册按钮之前,需要做几条校验逻辑:

1.用户名不能为空;

2.密码长度不能少于6位;

3.手机号码必须符合格式。

现在开始用策略模式实现:

第一步:把校验逻辑封装成策略对象

var strategies={
    isNotEmtpy:function(value, errorMsg){
        if(value==''){
            return errorMsg;
        }
    },
    minLenth: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;
        }
    }
}

第二步:准备实现Validator类,Validator类这里作为Context,负责接收用户的请求并委托给策略对象。

var Validator = function(){
    this.cache = [];  //保存校验规则
}
Validator.prototype.add=function(dom, rules){
    var _this=this;
    for(var i=0,rule;rule = rules[i++];){
        (function(rule){
            var strategyAry = rule.strategy.split(':');
            var errorMsg = rule.errorMsg;
            _this.cache.push(function(){
                var strategyName = strategyAry.shift();
                strategyAry.unshift(dom.value);
                strategyAry.push(errorMsg);
                return strategies[strategyName].apply(dom, strategyAry);
            })
        })(rule);
    }
}
Validator.prototype.start=function(){
    console.log(this.cache)
    for( var i=0, validatorFunc; validatorFunc = this.cache[i++]; ){
        var msg = validatorFunc();
        if(msg){
            return msg;
        }
    }
}

有了上面的策略对象和环境类,剩下的就是调用了。一下附上完整代码。

<!DOCTYPE html>
<html>
<head>
	<title>dmeo</title>
</head>
<body>
	<form id="registerForm" method="post">
		请输入用户名:<input type="text" name="username" />
		请输入密码:<input type="text" name="userpwd" />
		<button>提交</button>
	</form>
<script>
	/***************** 策略部分 ******************/
	var strategies={
		isNotEmtpy:function(value, errorMsg){
			if(value==''){
				return errorMsg;
			}
		},
		minLenth: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;
			}
		}
	}

	/***************** 环境Context部分 ******************/
	var Validator = function(){
		this.cache = [];  //保存校验规则
	}
	Validator.prototype.add=function(dom, rules){
		var _this=this;
		for(var i=0,rule;rule = rules[i++];){
			(function(rule){
				var strategyAry = rule.strategy.split(':');
				var errorMsg = rule.errorMsg;
				_this.cache.push(function(){
					var strategyName = strategyAry.shift();
					strategyAry.unshift(dom.value);
					strategyAry.push(errorMsg);
					return strategies[strategyName].apply(dom, strategyAry);
				})
			})(rule);
		}
	}

	Validator.prototype.start=function(){
		console.log(this.cache)
		for( var i=0, validatorFunc; validatorFunc = this.cache[i++]; ){
			var msg = validatorFunc();
			if(msg){
				return msg;
			}
		}
	}

	/***************** 调用部分 ******************/
	var validatorFn = function(){
		var validator = new Validator();
		validator.add(registerForm.username, [{strategy:'isNotEmtpy',errorMsg:'用户名不能为空!'},{strategy:'minLenth:4',errorMsg:'用户名长度不能少于4位!'}] );
		validator.add(registerForm.userpwd, [{strategy:'minLenth:6',errorMsg:'密码长度不能少于6位!'}]);
		var errorMsg = validator.start();
		return errorMsg;
	}

	var registerForm = document.getElementById('registerForm');
	registerForm.onsubmit = function(){
		var errorMsg = validatorFn();
		if(errorMsg){
			alert(errorMsg);
			return false;
		}
	}
</script>
</body>
</html>

还可以做成一个适合项目的校验插件,方便调用。

策略模式还可以有其他使用场景:可以用来封装一系列的"业务规则",单出现很多判断条件语句时,就可以思考一下是否可以使用策略模式。

如有错误,请指正!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章