• JS设计模式——策略模式


    核心:定义一些列的算法(逻辑)封装起来,并且它们是平等关系可以相互替换
    js中的策略模式关键字:策略和业务分离

    (一)基本实现

    常见代码:

    function playGame(gameName){
    	let str;
    	if(gameName == 'footBall'){
    		str = '不喜欢玩足球'
    	}else if(method == 'basketball'){
    		str = '不喜欢玩蓝球'
    	}else if(method == 'pingpang'){
    		str = '不喜欢玩乒乓'
    	}else if(method == 'swing'){
    		str = '好啊,我最喜欢游泳了'
    	}
    	alert(str)
    }
    

    策略模式优化

    let gameStrategies = {
    	'footBall': function(){
    		return '不喜欢玩足球'
    	},
    	'basketball': function(){
    		return '不喜欢玩蓝球'
    	},
    	'pingpang': function(){
    		return '不喜欢玩乒乓'
    	},
    	'swing': function(){
    		return '好啊,我最喜欢游泳了'
    	}
    }
    
    function playGame_1(gameName){
    	let str;
    	str = gameStrategies(gameName)
    	alert(str)
    }
    

      将策略单独提取出来封装,和业务代码分离。这样需要修改策略不需要去业务代码里面查找,而提取出来的策略也可以被多个业务代码复用。

    (二)场景案例

    //策略模式实现表单判断
    let formStrategies = {
    	isNonEmpty: 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
    		}
    	}
    }
    
    registerForm.onsubmit = function(){
    	let userNameErrorMsg = formStrategies.isNonEmpty(registerForm.userName,'用户名不能为空')
    	let pwdErrorMsg = formStrategies.minLength(registerForm.pwd,'密码长度不能少于6位')
    	let telErrorMsg = formStrategies.isMobile(registerForm.tel,'手机格式不正确')
    	if(userNameErrorMsg){
    		alert(userNameErrorMsg)
    	}else if(pwdErrorMsg){
    		alert(pwdErrorMsg)
    	}else if(telErrorMsg){
    		alert(telErrorMsg)
    	}
    }
    

      这里可以继续优化

    //start--------实现一个可配置策略的验证类
    function Validator(){
    	this.rules = []	//待验证规则队列
    }
    Validator.prototype.add = function(rule,dom,errorMsg){
    	let _rule = rule.split(':') //把策略和参数分开,比如minLength:6
    	this.rules.push(function(){
    		let strategy = _rule.shift() //策略字符串
    		_rule.unshift(dom.value)
    		_rule.push(errorMsg)
    		return formStrategies[strategy].apply(dom,_rule)
    
    	})
    }
    Validator.prototype.start = function(){
    	for(let i = 0,validatorFunc;validatorFunc = this.rules[i++];){
    		let msg = validatorFunc()
    		if(msg)return msg
    	}
    }
    //end-----------
    
    let validataFunc = function(){
    	let validator = new Validator()
    	validator.add(registerForm.userName,'isNonEmpty','用户名不能为空')
    	validator.add(registerForm.pwd,'minLength','密码长度不能少于6位')
    	validator.add(registerForm.tel,'isMobile','手机格式不正确')
    
    	let errorMsg = validator.start()
    	return errorMsg
    }
    
    registerForm.onsubmit = function(){
    	let errorMsg = validataFunc()
    	if(errorMsg){
    		alert(errorMsg)
    		return
    	}
    }
    

    (三)场景案例

    //上午返回'上午好';中午返回'中午';下午返回'下午好';晚上返回'晚上好';凌晨返回'凌晨了,请马上休息'
    function say(){
    	var hour = new Date().getHours()
    	if(hour > 6 && hour < 12){
    		return '上午好'
    	}else if(hour >= 12 && hour <= 13){
    		return '中午好'
    	}else if(hour > 13 && hour <18){
    		return '下午好'
    	}else if(hour >= 18 && hour < 24){
    		return '晚上好'
    	}else{
    		return '凌晨了,请马上休息'
    	}
    }
    //策略模式
    //语言策略
    var say_words = {
    	morning : function(){
    		return '上午好'
    	},
    	noon : function(){
    		return '中午好'
    	},
    	afternoon : function(){
    		return '下午好'
    	},
    	night : function(){
    		return '晚上好'
    	},
    	beforeDawn : function(){
    		return '凌晨了,请马上休息'
    	}
    }
    
    //时间策略
    var say_times = {
    	time6_12 : function(hour){
    		return hour > 6 && hour < 12
    	},
    	time12_13 : function(hour){	
    		return hour >= 12 && hour <= 13
    	},
    	time13_18 : function(hour){
    		return hour > 13 && hour <18
    	},
    	time18_24 : function(hour){
    		return hour >= 18 && hour < 24
    	},
    	time0_6 : function(hour){
    		return hour >= 0 && hour <= 6
    	},
    }
    
    function say1(){
    	var hour = new Date().getHours()			
    	if(say_times.time6_12){
    		return say_words.morning()
    	}else if(say_times.time12_13){
    		return say_words.noon()
    	}else if(say_times.time13_18){
    		return say_words.afternoon()
    	}else if(say_times.time18_24){
    		return say_words.night()
    	}else{
    		return say_words.beforeDawn()
    	}
    }
    
    //继续优化
    function say2(){
    	var hour = new Date().getHours()	
    	
    	//策略模式和多态思想结合
    	function doSayByStrategies(arr){
    		for(var i in arr){					
    			if(say_times[i](hour)){
    				return arr[i]()		
    			}
    		}
    	}
    	return doSayByStrategies({
    				time6_12:say_words.morning,
    				time12_13:say_words.noon,
    				time18_24:say_words.night
    			})
    	
    }
    

      这个例子其实并不是一个好例子,因为使用策略模式显得比直接使用if else语句更加繁琐,这个例子中如果say_words和say_times的逻辑比较复杂且需要很多场景共用,则该模式的好处将愈发显现。

  • 相关阅读:
    设计模式(一)基础面向对象
    面试题之三门问题
    「巫师3(The Witcher 3:Wild Hunt)」游戏测评
    欧拉角和四元数
    struts标签遍历各种list Map
    浅谈HtmlCleaner+XPath解析html或者xml
    hadoop简单例子
    解决JSP参数传递乱码的问题
    Set、List、Map的区别(浅谈)
    做个犀利的码农
  • 原文地址:https://www.cnblogs.com/webLilingyun/p/6553986.html
Copyright © 2020-2023  润新知