Maison >interface Web >js tutoriel >Utiliser un modèle de stratégie pour éviter le surconditionnement

Utiliser un modèle de stratégie pour éviter le surconditionnement

Linda Hamilton
Linda Hamiltonoriginal
2025-01-12 06:04:42781parcourir

Il y a quelques semaines, j'ai travaillé sur des solutions pour le Globo Player, où il fallait activer et désactiver des comportements spécifiques dans le logiciel lors de l'exécution. Ce type de besoin est généralement résolu avec des conditions chaînées, telles que if-else et switch, mais cette approche n'est pas toujours idéale.

Dans cet article, je vous présente une solution qui a parfaitement relevé ce défi et qui peut s'appliquer à différents scénarios de programmation.

Quelle stratégie dois-je utiliser ?

Imaginez que vous venez d'arriver dans une destination inconnue. En quittant l’aéroport, vous disposez de plusieurs options pour vous rendre à votre hôtel. L’alternative la moins chère est de louer un vélo, mais cela prendrait plus de temps. Prendre un bus coûterait un peu plus cher, mais cela vous amènerait plus rapidement et en toute sécurité. Enfin, louer une voiture serait l'option la plus rapide, mais aussi la plus chère.

Usando Strategy Pattern para evitar condicionamento exagerado

Le point le plus important dans cette situation est de comprendre que, quelle que soit la stratégie choisie, l'objectif final est le même : arriver à l'hôtel.

Cette analogie peut être appliquée au développement de logiciels. Lorsque nous traitons de scénarios dans lesquels différents processus cherchent à atteindre le même objectif, nous pouvons utiliser le modèle de conception stratégique pour nous aider.

Quand on programme sans stratégie...

Imaginez que nous devions développer un système bancaire capable de calculer des frais en fonction du type de compte du client, tel que courant, épargne ou prime. Ces calculs doivent être effectués au moment de l'exécution, ce qui nécessite une implémentation qui dirige correctement le flux de code vers le calcul approprié.

En principe, une approche courante consisterait à utiliser une structure simple de conditions chaînées pour résoudre le problème rapidement et de manière fonctionnelle :

class Banco {
  calcularTaxa(tipoConta, valor) {
    if (tipoConta === "corrente") {
      return valor * 0.02; // 2% de taxa
    } else if (tipoConta === "poupanca") {
      return valor * 0.01; // 1% de taxa
    } else if (tipoConta === "premium") {
      return valor * 0.005; // 0,5% de taxa
    } else {
      throw new Error("Tipo de conta não suportado.");
    }
  }
}

const banco = new Banco();
const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00
console.log(`A taxa para sua conta é: R$${taxa}`);

Bien que cette solution fonctionne bien pour des scénarios simples, que se passe-t-il si la banque doit ajouter cinq types de comptes supplémentaires à l'avenir ?

calcularTaxa(tipoConta, valor) {
  if (tipoConta === "corrente") {
    return valor * 0.02; // 2% de taxa
  } else if (tipoConta === "poupanca") {
    return valor * 0.01; // 1% de taxa
  } else if (tipoConta === "premium") {
    return valor * 0.005; // 0,5% de taxa
  } else if (tipoConta === "estudante") {
    return valor * 0.001; // 0,1% de taxa
  } else if (tipoConta === "empresarial") {
    return valor * 0.03; // 3% de taxa
  } else if (tipoConta === "internacional") {
    return valor * 0.04 + 10; // 4% + taxa fixa de R
  } else if (tipoConta === "digital") {
    return valor * 0.008; // 0,8% de taxa
  } else if (tipoConta === "exclusiva") {
    return valor * 0.002; // 0,2% de taxa
  } else {
    throw new Error("Tipo de conta inválido!");
  }
}

Maintenant, le code commence à montrer de sérieuses limitations. Explorons les problèmes de cette approche :

1. Faible évolutivité

Chaque fois qu'un nouveau type de compte doit être ajouté, la méthode calculateRate doit être modifiée. Cela augmente continuellement le nombre de conditions, rendant le code plus complexe et difficile à gérer.

2. Forte dépendance

La logique de calcul du taux est entièrement couplée à la méthode calculateRate. Les modifications apportées à un type de compte peuvent avoir un impact par inadvertance sur d'autres, augmentant ainsi le risque d'introduction de bugs.

3. Répétition de code

Des extraits similaires, tels que montant * frais, sont dupliqués pour chaque type de compte. Cela réduit la réutilisation du code et viole le principe DRY (Ne vous répétez pas).

Dans la prochaine étape, nous verrons comment le modèle de stratégie peut résoudre ces problèmes, en promouvant un code plus propre, évolutif et modulaire.

Une stratégie à la fois !

Pour éviter les problèmes mentionnés ci-dessus, nous traiterons chaque type de compte comme une entité isolée dans le logiciel. En effet, chaque type de compte a un calcul de frais spécifique et peut avoir d'autres comportements futurs associés.

Au lieu de créer une classe Bank avec une méthode calculateRate qui résout toutes les opérations, créons une classe pour chaque type de compte :

class Banco {
  calcularTaxa(tipoConta, valor) {
    if (tipoConta === "corrente") {
      return valor * 0.02; // 2% de taxa
    } else if (tipoConta === "poupanca") {
      return valor * 0.01; // 1% de taxa
    } else if (tipoConta === "premium") {
      return valor * 0.005; // 0,5% de taxa
    } else {
      throw new Error("Tipo de conta não suportado.");
    }
  }
}

const banco = new Banco();
const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00
console.log(`A taxa para sua conta é: R$${taxa}`);

Cela garantit que chaque opération de calcul est conservée dans un périmètre spécifique pour votre type de compte. Désormais, nous avons des comportements isolés axés sur chaque type de compte :

Usando Strategy Pattern para evitar condicionamento exagerado


Architecture de solutions basée sur des stratégies.

Mais, où se situera la sélection de compte souhaitée ?

calcularTaxa(tipoConta, valor) {
  if (tipoConta === "corrente") {
    return valor * 0.02; // 2% de taxa
  } else if (tipoConta === "poupanca") {
    return valor * 0.01; // 1% de taxa
  } else if (tipoConta === "premium") {
    return valor * 0.005; // 0,5% de taxa
  } else if (tipoConta === "estudante") {
    return valor * 0.001; // 0,1% de taxa
  } else if (tipoConta === "empresarial") {
    return valor * 0.03; // 3% de taxa
  } else if (tipoConta === "internacional") {
    return valor * 0.04 + 10; // 4% + taxa fixa de R
  } else if (tipoConta === "digital") {
    return valor * 0.008; // 0,8% de taxa
  } else if (tipoConta === "exclusiva") {
    return valor * 0.002; // 0,2% de taxa
  } else {
    throw new Error("Tipo de conta inválido!");
  }
}

Notez qu'au lieu de créer des structures de décision chaînées (if-else), nous avons choisi de passer un compte, une stratégie dans le constructeur de notre classe Banque. Cela permet à la méthode setConta de sélectionner le type de compte souhaité au moment de l'exécution lors de l'instanciation de la banque. Le calcul du taux sera effectué via this.conta.calcularTaxa(valor).

class ContaCorrente {
  calcularTaxa(valor) {
    return valor * 0.02; // 2% de taxa
  }
}

class ContaPoupanca {
  calcularTaxa(valor) {
    return valor * 0.01; // 1% de taxa
  }
}

class ContaPremium {
  calcularTaxa(valor) {
    return valor * 0.005; // 0,5% de taxa
  }
}

Avec ce modèle, nous avons pu appliquer le modèle de stratégie de manière simple, garantissant une mise en œuvre plus flexible, évolutive et à faible couplage.

Puis-je utiliser la stratégie dans tout ?

Le Strategy Pattern est une solution puissante lorsque vous devez faire varier le comportement d'une opération au moment de l'exécution, sans coupler directement le code d'exécution à différentes conditions ou types. Ce modèle est idéal pour les scénarios où le comportement d'une opération peut varier en fonction du contexte et où les alternatives sont indépendantes les unes des autres.

Quand utiliser le modèle de stratégie

  • Comportements variables : lorsque le comportement d'un système doit être modifié de manière dynamique en fonction de conditions spécifiques (telles que différents types de comptes dans l'exemple bancaire).
  • Évitez les conditions complexes : Lorsque la logique de décision est basée sur de nombreuses structures de contrôle de flux, telles que plusieurs if-else ou switch, ce qui rend le code difficile à maintenir.
  • Facilité de maintenance et d'extension : Lorsque vous souhaitez ajouter de nouveaux comportements sans modifier le code existant, créez simplement de nouvelles classes de stratégie.
  • Découplage des comportements : lorsque vous souhaitez isoler des comportements spécifiques dans différentes classes, rendant le code plus modulaire et flexible.

En utilisant Strategy, nous garantissons que le code devient plus propre, modulaire et flexible, en plus de favoriser une meilleure maintenance et expansion du système.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn