Padrões de design JavaScript: o padrão de estratégia

Definição de Padrão de Estratégia

A definição de padrão de estratégia é definir um objeto de estratégia que encapsula uma série de algoritmos, e os algoritmos podem ser alternados de maneira flexível para uso.
Ele resolve principalmente os problemas complexos e difíceis de manter causados ​​pelo uso de if e else quando existem vários algoritmos semelhantes.

Exemplo de padrão de estratégia

Um dia, o ferreiro a fez uma espada sa e afirmou que sua espada era a melhor em todo o círculo de ferreiros. Ele orgulhosamente se exibia na frente de seus colegas o dia todo.
A história se espalhou lentamente, e o Ferreiro B na cidade próxima ficou infeliz quando ouviu isso, então ele pegou seu trabalho favorito, Espada SB, para competir com o Ferreiro A.
Os dados das duas espadas são os seguintes:

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

O ferreiro A coçou a barba, sorriu e tirou o comparador de nitidez. Os dois colocaram as espadas nele. O comparador ficou assim:

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

Comparador iniciado

	compareSharpness(sword1, sword2)

O resultado é uma vitória. O Ferreiro B olhou para ele e disse que havia algo errado com o seu comparador. Como as espadas poderiam apenas comparar sua nitidez? Não, você precisa adicionar um grau de vulnerabilidade. Então o ferreiro B pegou um comparador e colocou-o na mesa. O comparador ficou assim:

	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 começa:

	compareSharpnessAndDurability(sword1, sword2)

Obviamente a espada venceu. Mas foi a vez do Ferreiro A ficar insatisfeito, dizendo que era uma espada mágica que poderia liberar uma grande magia – destruindo o mundo. O Ferreiro B respondeu, não seja complacente, eu também posso liberar uma grande magia – Aniquilação Sagrada. Então os dois compraram juntos um novo 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 + '胜利')
		}
	}

Desta vez, SA venceu novamente. O Ferreiro B disse que estava convencido e desistiu, mas achou que algo estava errado. A mágica estava um pouco errada. Por que a pontuação estava tão diferente? Então ele calmamente abordou a empresa comparadora.
A empresa Comparator fez uma pequena pesquisa e disse que as proporções de pontuação de magia e vulnerabilidade não deveriam ser calculadas desta forma, e a espada tem mais dados e precisa ser alterada para uma lógica mais complexa. Assim nasceu um comparador contendo dezenas de if-else e milhares de linhas... Mais tarde, os desenvolvedores disseram que não tinham como começar.
Então, e se você usar o padrão de estratégia?
Encapsule as estratégias de comparação em um objeto e selecione dinamicamente a estratégia de comparação com base no nome do atributo do objeto.
O código ficará assim:

	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 + '胜利')
		}
	}

No futuro, quer você adicione atributos a serem comparados ou modifique o método de comparação de atributos, você só precisará alterá-los na estratégia.Mesmo estratégias diferentes podem ser separadas e escritas em arquivos diferentes.

Vantagens e desvantagens do padrão de estratégia

Vantagens: 1. O algoritmo pode ser alternado livremente. 2. Evite usar julgamentos condicionais múltiplos. 3. Boa escalabilidade.

Desvantagens: 1. O número de funções estratégicas aumentará.

Cenários de uso do padrão de estratégia

  • Um sistema precisa escolher dinamicamente um dos vários algoritmos.
  • Um objeto possui muitos comportamentos, que são implementados usando múltiplas instruções de seleção condicional.

Validador de formulário baseado em padrão de estratégia

Com base na minha compreensão do padrão de estratégia, escrevi um validador de formulário baseado no padrão de estratégia.
Primeiro defina um construtor Validador.

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

O cache é a função de verificação usada para registrar todas as strings que precisam ser verificadas agora.
errFunc é uma função usada para lidar com informações de erro.
Defina outro objeto de estratégia.

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;
      }
    };
  },
};

Quatro estratégias de validação de formulário comumente usadas no desenvolvimento são definidas na estratégia, incluindo julgamento nulo, restrições de comprimento máximo e mínimo e verificação de número de telefone celular. O último parâmetro em cada estratégia é uma mensagem de erro. A seguir vem a adição de estratégias de verificação.Um valor pode ter múltiplas estratégias de verificação.

/**
 * 
 * @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))
    }
}

As estratégias de parâmetros precisam ser passadas em uma ou mais das séries de estratégias acabadas de definir. Todas as funções serão colocadas no cache até que o método de verificação seja acionado.

/**
 * 验证所有的值的合法性
 */
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
}

O método check executará todas as funções no cache e retornará false se uma incompatibilidade for encontrada.

Uso de validadores de formulário

Apenas olhar para o código pode tornar o uso deste validador de formulário um pouco confuso. Aqui estão alguns exemplos de como usar o validador de formulário.

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()

Você também pode preencher a estratégia na forma de um array no segundo parâmetro do método add.

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

Se não houver problema com a string verificada, validator.check() retornará verdadeiro. Se a string verificada não atender aos requisitos da estratégia de verificação, validator.check() retornará falso e chamará a função de prompt de erro com o erro informações como o primeiro parâmetro. , solicitando uma mensagem de erro.

Acho que você gosta

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