策略模式學習筆記

平時我們在寫代碼時會偶爾用到策略模式的思想,但我們卻不自知。今天學習了策略模式,特記錄如下:

策略模式的定義是:定義一系列的算法,把他們一個個封裝起來,並且使它們可以相互替換。

策略模式的目的是:將算法的使用和實現分離開來。一個基於策略模式的程序至少由兩部分組成。第一部分是一組策略類,策略類封裝了具體的算法,並負責具體的計算過程。第二部分是環境類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>

還可以做成一個適合項目的校驗插件,方便調用。

策略模式還可以有其他使用場景:可以用來封裝一系列的"業務規則",單出現很多判斷條件語句時,就可以思考一下是否可以使用策略模式。

如有錯誤,請指正!

 

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