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的逻辑比较复杂且需要很多场景共用,则该模式的好处将愈发显现。

原文地址:https://www.cnblogs.com/webLilingyun/p/6553986.html