Aplicación de patrón de estrategia JavaScript

Recientemente, he estado leyendo el libro "Patrones de diseño de JavaScript y prácticas de desarrollo", y me he beneficiado mucho. Grabe las demostraciones en el libro para profundizar su comprensión.

El tema de cada patrón de diseño es separar la parte no modificada de la parte modificada, y el patrón de estrategia no es una excepción. El propósito del patrón de estrategia es separar el uso del algoritmo de la implementación del algoritmo.

La definición del patrón de estrategia es: definir una serie de algoritmos, encapsularlos uno por uno y hacer que se reemplacen entre sí.

Un programa basado en un patrón de estrategia consta de al menos dos partes. La primera parte es un conjunto de clases de estrategia, que encapsulan algoritmos específicos y son responsables del proceso de cálculo específico. La segunda parte es el contexto de clase de entorno, que acepta solicitudes de clientes y luego delega la solicitud a una clase de estrategia. Para hacer esto, significa que una referencia a un objeto de estrategia debe mantenerse en el contexto.

demo1:

Los premios de fin de año de muchas empresas se basan en las bases salariales de los empleados y el rendimiento de fin de año. Por ejemplo, una persona con desempeño S tiene un bono de fin de año de 4 veces el salario, una persona con desempeño A tiene un salario de tres años y una persona con desempeño B recibe el doble del salario. Supongamos que el departamento de finanzas nos pide que proporcionemos un código para facilitarles el cálculo de la bonificación de fin de año de los empleados. Implementar esto con JS es simple:

var calculateBonus = function(performanceLevel, salary) {
	if (performanceLevel === 'S') {
		return salary * 4;
	}
	if (performanceLevel === 'A') {
		return salary * 3;
	}
	if (performanceLevel === 'B') {
		return salary * 2;
	}
};
calculateBonus('B', 20000); // 输出:40000
calculateBonus('S', 6000); // 输出:24000

Este código es muy simple, pero las desventajas son obvias:

  1. La función CalculateBonus es relativamente grande y contiene muchas instrucciones if-else, que deben cubrir todas las ramas lógicas.
  2. La función CalculateBonus carece de flexibilidad. Si se agrega un nuevo nivel de rendimiento C, o si el coeficiente de bonificación de rendimiento S se cambia a 5, entonces debemos profundizar en la implementación interna de la función CalculateBonus, que viola el principio abierto y cerrado.
  3. La reutilización del algoritmo es deficiente. ¿Qué sucede si necesitamos reutilizar estos algoritmos para calcular las bonificaciones en otras partes del programa? Nuestra elección es solo copiar y pegar.

En este momento, se utiliza el modo de estrategia; vea el código:

var strategies = {
	"S": function(salary) {
		return salary * 4;
	},
	"A": function(salary) {
		return salary * 3;
	},
	"B": function(salary) {
		return salary * 2;

	}
};
var calculateBonus = function(level, salary) {
	return strategies[level](salary);
};
console.log(calculateBonus('S', 20000)); // 输出:80000
console.log(calculateBonus('A', 10000)); // 输出:30000

Al refactorizar el código utilizando el patrón de estrategia anterior, nosotros 消除了原程序中大片的条件分支语句. Toda la lógica relacionada con el cálculo de la bonificación ya no se coloca en el contexto, sino en su lugar 分布在各个策略对象中. El contexto no tiene la capacidad de calcular bonificaciones, sino más bien esta responsabilidad 委托给了某个策略对象, el algoritmo responsable de cada objeto de estrategia se ha encapsulado dentro del objeto.

demo2 implementa un DIV de movimiento en js:

Use el modo de estrategia para lograr lo siguiente:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>javascript策略模式的应用!</title>
</head>
<body>
<div style="position:absolute;background:blue; width: 100px;height: 100px;color: #fff;" id="div">我是div</div>
	<script>
 
		var tween = {
			linear: function(t, b, c, d) {
				return c * t / d + b;
			},
			easeIn: function(t, b, c, d) {
				return c * (t /= d) * t + b;
			},
			strongEaseIn: function(t, b, c, d) {
				return c * (t /= d) * t * t * t * t + b;
			},
			strongEaseOut: function(t, b, c, d) {
				return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
			},
			sineaseIn: function(t, b, c, d) {
				return c * (t /= d) * t * t + b;
			},
			sineaseOut: function(t, b, c, d) {
				return c * ((t = t / d - 1) * t * t + 1) + b;
			}
		};
		var Animate = function(dom) {
			this.dom = dom; // 进行运动的dom 节点
			this.startTime = 0; // 动画开始时间
			this.startPos = 0; // 动画开始时,dom 节点的位置,即dom 的初始位置
			this.endPos = 0; // 动画结束时,dom 节点的位置,即dom 的目标位置
			this.propertyName = null; // dom 节点需要被改变的css 属性名
			this.easing = null; // 缓动算法
			this.duration = null; // 动画持续时间
		};
		Animate.prototype.start = function(propertyName, endPos, duration, easing) {
			this.startTime = +new Date; // 动画启动时间
			this.startPos = this.dom.getBoundingClientRect()[propertyName]; // dom 节点初始位置
			this.propertyName = propertyName; // dom 节点需要被改变的CSS 属性名
			this.endPos = endPos; // dom 节点目标位置
			this.duration = duration; // 动画持续事件
			this.easing = tween[easing]; // 缓动算法
			var self = this;
			var timeId = setInterval(function() { // 启动定时器,开始执行动画
				if (self.stop() === false) { // 如果动画已结束,则清除定时器
					clearInterval(timeId);
				}
			}, 19);
		};
		Animate.prototype.stop = function() {
			var t = +new Date; // 取得当前时间
			if (t >= this.startTime + this.duration) { // (1)
				this.update(this.endPos); // 更新小球的CSS 属性值
				return false;
			}
			var pos = this.easing(t - this.startTime, this.startPos,
				this.endPos - this.startPos, this.duration);
			// pos 为小球当前位置
			this.update(pos); // 更新小球的CSS 属性值
		};
		Animate.prototype.update = function(pos) {
			this.dom.style[this.propertyName] = pos + 'px';
		};

		var div = document.getElementById('div');
		var animate = new Animate(div);
		animate.start('left', 500, 1000, 'strongEaseOut');

	</script>
</body>
</html>

Usamos el modo de estrategia para pasar el algoritmo a la clase de animación para lograr una variedad de efectos de cámara lenta. Estos algoritmos se pueden reemplazar fácilmente con otro algoritmo. Esta es una de las aplicaciones clásicas del modo de estrategia. Implementar el patrón de estrategia no es complicado, la clave es cómo implementar el patrón de estrategia por detrás, encontrar 封装变化, 委托y 多态性éstos 思想的价值.

Publicados 398 artículos originales · ganado elogios 182 · vistas 370 000 +

Supongo que te gusta

Origin blog.csdn.net/yexudengzhidao/article/details/105505344
Recomendado
Clasificación