Patrones de diseño de JavaScript: patrón de estrategia

Definición de patrón estratégico

La definición del patrón de estrategia es definir un objeto de estrategia, encapsular una serie de algoritmos y los algoritmos se pueden cambiar de manera flexible.
Resuelve principalmente los problemas complejos y difíciles de mantener causados ​​por el uso de if y else en el caso de múltiples algoritmos similares.

Ejemplo de patrón de estrategia

Un día, el herrero a hizo una espada y afirmó que su espada era la mejor de todo el círculo de herreros. La exhibió con orgullo frente a sus compañeros durante todo el día.
La historia se difundió lentamente, y el herrero B de la ciudad vecina no estaba contento cuando la escuchó, por lo que trajo su obra favorita, la espada sb, para competir con el herrero A.
Los datos de las dos espadas son los siguientes:

	const sword1 = {
    
    
		name: 'sa',//宝剑的名字sa
		sharpness: 999,//宝剑的锋利度,这数据确实是值得吹嘘
		vulnerability: 100,//宝剑的脆弱度,可以说是比较脆弱了
		magic: '101',//宝剑的魔法ID
	}
	const sword2 = {
    
    
		name: 'sb',//宝剑的名字sb
		sharpness: 500,//宝剑的锋利度,也是一把锋利的绝世好剑
		vulnerability: 10,//宝剑的脆弱度,这把剑算得上比较坚硬
		magic: '102',//宝剑的魔法ID
	}

El herrero A se acarició la barba y sonrió, sacó el comparador de nitidez y los dos le pusieron la espada, el comparador se veía así:

	function compareSharpness (s1, s2) {
    
    
		if (s1.sharpness > s2.sharpness) {
    
    
			console.log(s1.name + '胜利')
		} else {
    
    
			console.log(s2.name + '胜利')
		}
	}

Comparador iniciado

	compareSharpness(sword1, sword2)

El resultado es una victoria. El herrero B inmediatamente dijo que algo anda mal con su comparador: ¿Cómo se pueden comparar las espadas solo en términos de filo? No, hay que añadir la vulnerabilidad. Entonces el herrero B sacó un comparador y lo golpeó sobre la mesa. Este comparador se ve así:

	function compareSharpnessAndDurability (s1, s2) {
    
    
		const point = 0
		for (let key in s1) {
    
    
			if (key === 'sharpness') {
    
    
				point += (s1[key] - s2[key])
			} else if (key === 'vulnerability') {
    
    
				point += ((s2[key] - s1[key]) * 10)
				//脆弱度是越低越好的,而且脆弱评分的比例要比锋利度高
			}
		}
		if (point > 0) {
    
    
			console.log(s1.name + '胜利')
		} else {
    
    
			console.log(s2.name + '胜利')
		}
	}

Este comparador comienza:

	compareSharpnessAndDurability(sword1, sword2)

Obviamente ganó la espada. Pero fue el turno del Herrero A de estar insatisfecho, diciendo que era una espada mágica que podía liberar una gran magia, destruyendo el mundo. El herrero B respondió, no seas complaciente, también puedo liberar una gran magia: Santa Aniquilación. Entonces los dos compraron conjuntamente un nuevo comparador:

	//这个比较器比较先进,记录了一些魔法的评分
	const magicList = {
    
    
		'101': {
    
    
			name: '毁天灭地',
			point: 7000
		},
		'102': {
    
    
			name: '神圣湮灭',
			point: 6000
		}
	}
	function compareSword (s1, s2) {
    
    
		const point = 0
		for (let key in s1) {
    
    
			if (key === 'sharpness') {
    
    
				point += (s1[key] - s2[key])
			} else if (key === 'vulnerability') {
    
    
				point += ((s2[key] - s1[key]) * 10)
				//脆弱度是越低越好的,而且脆弱评分的比例要比锋利度高
			} else if (key === 'magic') {
    
    
				point += (magicList[s1[key]].point - magicList[s2[key]].point)
				//魔法评分要读取魔法表
			}
		}
		if (point > 0) {
    
    
			console.log(s1.name + '胜利')
		} else {
    
    
			console.log(s2.name + '胜利')
		}
	}

Esta vez, SA volvió a ganar. El herrero B dijo que estaba convencido y se rindió, pero pensó que algo andaba mal. La magia estaba un poco fuera de lugar. ¿Por qué la puntuación era tan diferente? Así que se acercó silenciosamente a la empresa de comparación.
La compañía Comparator investigó un poco y dijo que las proporciones de puntuación de magia y vulnerabilidad no deben calcularse de esta manera, y que la espada tiene más datos y debe cambiarse a una lógica más compleja. Así nació un comparador que contiene docenas de if-else y miles de líneas... Los desarrolladores posteriores dijeron que no tenían forma de comenzar.
Entonces, ¿qué pasa si utilizamos el patrón de estrategia?
Encapsule las estrategias de comparación en un objeto y seleccione dinámicamente la estrategia de comparación según el nombre del atributo del objeto.
El código quedará así:

	const strats = {
    
    
		sharpness: function (v1, v2) {
    
    
			return v1 - v2
		},
		vulnerability: function (v1, v2) {
    
    
			return (v2 - v1) * 10
		},
		magic: function (v1, v2) {
    
    
			return magicList[v1].point - magicList[v2].point
		},
	}
	const magicList = {
    
    
		'101': {
    
    
			name: '毁天灭地',
			point: 7000
		},
		'102': {
    
    
			name: '神圣湮灭',
			point: 6000
		}
	}
	function compareSword (s1, s2) {
    
    
		const point = 0
		for (let key in s1) {
    
    
			point += strats[key](s1[key], s2[key])
		}
		if (point > 0) {
    
    
			console.log(s1.name + '胜利')
		} else {
    
    
			console.log(s2.name + '胜利')
		}
	}

En el futuro, ya sea que agregue atributos para comparar o modifique el método de comparación de atributos, solo necesitará cambiarlos en la estrategia, e incluso diferentes estrategias se pueden separar y escribir en diferentes archivos.

Ventajas y desventajas del patrón estratégico

Ventajas: 1. El algoritmo se puede cambiar libremente. 2. Evite utilizar múltiples juicios condicionales. 3. Buena escalabilidad.

Desventajas: 1. Aumentará el número de funciones estratégicas.

Escenarios de uso del patrón estratégico.

  • Un sistema necesita elegir dinámicamente uno de varios algoritmos.
  • Un objeto tiene muchos comportamientos, que se implementan mediante múltiples declaraciones de selección condicional.

Validador de formularios basado en patrón de estrategia.

Según mi comprensión del patrón de estrategia, escribí un validador de formulario basado en el patrón de estrategia.
Primero defina una función constructora Validador.

const Validator = function(errFunc){
    
    
    this.cache=[]
    this.errFunc=errFunc
}

Entre ellos, el caché es una función de verificación que se utiliza para registrar todas las cadenas que deben verificarse ahora.
errFunc es una función utilizada para manejar mensajes de error.
Defina otro objeto de política.

Validator.strategies = {
    
    
  /**
   * @param {string} errorMsg - 错误信息
   */
  isNonEmpty: function (errorMsg) {
    
    
    if(!errorMsg){
    
    
      errorMsg="输入不能为空"
    }
    return function (value) {
    
    
      if (value === "") {
    
    
        return errorMsg;
      }
    };
  },
  /**
   * @param {number} length - 最小长度
   * @param {string} errorMsg - 错误信息
   */
  minLength: function (length, errorMsg) {
    
    
    if(!errorMsg){
    
    
      errorMsg="输入内容过少"
    }
    return function (value) {
    
    
      if (value.length < length) {
    
    
        return errorMsg;
      }
    };
  },
  /**
   * @param {number} length - 最大长度
   * @param {string} errorMsg - 错误信息
   */
  maxLength: function (length, errorMsg) {
    
    
    if(!errorMsg){
    
    
      errorMsg="输入内容不能超出长度限制"
    }
    return function (value) {
    
    
      if (value.length > length) {
    
    
        return errorMsg;
      }
    };
  },
  /**
   * @param {string} errorMsg - 错误信息
   */
  isMobile: function (errorMsg) {
    
    
    if(!errorMsg){
    
    
      errorMsg="手机号输入有误"
    }
    return function (value) {
    
    
      if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
    
    
        return errorMsg;
      }
    };
  },
};

En la estrategia, se definen cuatro estrategias de verificación de formularios de uso común, incluido el juicio vacío, las restricciones de longitud máxima y mínima y la verificación de números de teléfonos móviles. El último parámetro de cada estrategia es un mensaje de error. Lo siguiente es agregar estrategias de validación; un valor puede validarse mediante múltiples estrategias.

/**
 * 
 * @param {string} value - 待验证字符串
 * @param {function} strategies - 验证策略
 */
Validator.prototype.add=function(value,strategies){
    
    
    if(strategies instanceof Array){
    
    
        for(var i=0;i<strategies;i++){
    
    
            this.cache.push(strategies[i].bind(null,value))
        }
    }else{
    
    
        this.cache.push(strategies.bind(null,value))
    }
}

Las estrategias de parámetros deben pasarse en una o más de la serie de estrategias recién definidas. Todas las funciones se enviarán al caché hasta que se active el método de verificación.

/**
 * 验证所有的值的合法性
 */
Validator.prototype.check=function(retain){
    
    
    for(var i=0;i<this.cache.length;i++){
    
    
        var msg=this.cache[i]()
        if(msg){
    
    
            this.errFunc(msg)
            return false
        }
    }
    if(!retain){
    
    
        this.cache=[]
    }
    return true
}

El método de verificación ejecutará todas las funciones en el caché y devolverá falso si no se encuentra ninguna coincidencia.

Uso de validadores de formularios.

Solo mirar el código puede resultar un poco vago sobre el uso de este validador de formularios. A continuación se muestran algunos ejemplos del uso de validadores de formularios.

var text = "123456"
var validator = new Validator(console.log)//传入这个函数是用于提示错误信息的,可以传入$alert来提示错误信息
validator.add(text,Validator.strategies.minLength(4,'长度未达到要求!'))//加入最小长度为4的验证策略
validator.add(text,Validator.strategies.maxLength(6,'太长了!!!'))//加入最大长度为6
validator.check()

También puede completar la estrategia en forma de matriz en el segundo parámetro del método agregar.

//同等效果
validator.add(text,[Validator.strategies.minLength(4),Validator.strategies.maxLength(6)])
//验证策略的错误信息有默认值,可不填
validator.check()

Si no hay ningún problema con la cadena verificada, validator.check() devolverá verdadero. Si la cadena verificada no cumple con los requisitos de la estrategia de verificación, validator.check() devolverá falso y llamará a la función de aviso de error con el error. información como primer parámetro. , lo que genera un mensaje de error.

Supongo que te gusta

Origin blog.csdn.net/rdxtfcec/article/details/126153806
Recomendado
Clasificación