image de chargement
Retour au glossaire

Strategy Pattern

Patron de conception comportemental permettant de définir une famille d'algorithmes interchangeables et de les rendre indépendants des clients.

Mis à jour le 11 janvier 2026

Le pattern Strategy est un patron de conception comportemental qui permet de définir une famille d'algorithmes, de les encapsuler individuellement et de les rendre interchangeables. Ce pattern permet à l'algorithme de varier indépendamment des clients qui l'utilisent, favorisant ainsi la composition plutôt que l'héritage. Il constitue une alternative élégante aux structures conditionnelles complexes et facilite l'ajout de nouveaux comportements sans modifier le code existant.

Fondements du Pattern Strategy

  • Encapsulation des algorithmes dans des classes séparées implémentant une interface commune
  • Découplage entre le contexte d'utilisation et l'implémentation concrète de l'algorithme
  • Sélection dynamique de l'algorithme à exécuter en fonction du contexte métier
  • Conformité au principe Open/Closed : ouvert à l'extension, fermé à la modification

Avantages du Pattern Strategy

  • Élimination des structures conditionnelles complexes (if/switch) en faveur du polymorphisme
  • Facilite les tests unitaires en permettant l'isolation et le mock de chaque stratégie
  • Améliore la maintenabilité en isolant chaque algorithme dans sa propre classe
  • Permet le changement de comportement à l'exécution sans impacter le code client
  • Respecte le principe de responsabilité unique en séparant les préoccupations algorithmiques

Exemple Concret : Système de Paiement

payment-strategy.ts
// Interface commune pour toutes les stratégies
interface PaymentStrategy {
  pay(amount: number): Promise<PaymentResult>;
  validate(): boolean;
}

// Stratégie concrète : Carte bancaire
class CreditCardStrategy implements PaymentStrategy {
  constructor(
    private cardNumber: string,
    private cvv: string,
    private expiryDate: string
  ) {}

  validate(): boolean {
    return this.cardNumber.length === 16 && this.cvv.length === 3;
  }

  async pay(amount: number): Promise<PaymentResult> {
    console.log(`Processing ${amount}€ via Credit Card`);
    // Logique de paiement par carte
    return { success: true, transactionId: 'CC-' + Date.now() };
  }
}

// Stratégie concrète : PayPal
class PayPalStrategy implements PaymentStrategy {
  constructor(private email: string) {}

  validate(): boolean {
    return this.email.includes('@');
  }

  async pay(amount: number): Promise<PaymentResult> {
    console.log(`Processing ${amount}€ via PayPal`);
    // Logique de paiement PayPal
    return { success: true, transactionId: 'PP-' + Date.now() };
  }
}

// Stratégie concrète : Crypto
class CryptoStrategy implements PaymentStrategy {
  constructor(private walletAddress: string) {}

  validate(): boolean {
    return this.walletAddress.startsWith('0x');
  }

  async pay(amount: number): Promise<PaymentResult> {
    console.log(`Processing ${amount}€ via Cryptocurrency`);
    // Logique de paiement crypto
    return { success: true, transactionId: 'CRYPTO-' + Date.now() };
  }
}

// Contexte qui utilise la stratégie
class PaymentProcessor {
  private strategy: PaymentStrategy;

  setStrategy(strategy: PaymentStrategy): void {
    this.strategy = strategy;
  }

  async processPayment(amount: number): Promise<PaymentResult> {
    if (!this.strategy.validate()) {
      throw new Error('Invalid payment method configuration');
    }
    return await this.strategy.pay(amount);
  }
}

// Utilisation
const processor = new PaymentProcessor();

// Client A : paiement par carte
processor.setStrategy(new CreditCardStrategy('1234567890123456', '123', '12/25'));
await processor.processPayment(99.99);

// Client B : paiement PayPal
processor.setStrategy(new PayPalStrategy('user@example.com'));
await processor.processPayment(49.50);

// Client C : paiement crypto
processor.setStrategy(new CryptoStrategy('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'));
await processor.processPayment(199.00);

Mise en Œuvre du Pattern Strategy

  1. Identifier les algorithmes ou comportements qui varient et qui sont susceptibles de changer
  2. Définir une interface commune (Strategy) avec les méthodes que toutes les stratégies doivent implémenter
  3. Créer des classes concrètes pour chaque variante d'algorithme implémentant l'interface Strategy
  4. Développer une classe Context qui maintient une référence vers l'objet Strategy et délègue l'exécution
  5. Permettre au client de choisir et d'injecter la stratégie appropriée dans le contexte
  6. Tester chaque stratégie de manière isolée pour garantir leur bon fonctionnement

Conseil Pro

Combinez le pattern Strategy avec l'injection de dépendances pour maximiser la flexibilité. Utilisez une factory ou un service locator pour sélectionner la stratégie appropriée en fonction de critères métier (pays, profil utilisateur, montant).

Outils et Frameworks Associés

  • TypeScript - Typage fort des interfaces de stratégie pour une meilleure sécurité
  • NestJS - Providers et injection de dépendances pour gérer les stratégies
  • Redux - Reducers comme stratégies de transformation d'état
  • Passport.js - Authentification basée sur des stratégies interchangeables
  • Joi/Yup - Validation avec stratégies de schéma configurables
  • AWS SDK - Stratégies de retry et de gestion d'erreurs personnalisables

Le pattern Strategy représente un investissement stratégique dans la maintenabilité et l'évolutivité du code. En isolant les algorithmes métier dans des composants interchangeables, les équipes peuvent itérer rapidement sur les fonctionnalités.

L'argentestdéjàsurlatable.

En 1 heure, découvrez exactement combien vous perdez et comment le récupérer.

Agence de développement web, automatisation & IA

contact@peaklab.fr
Newsletter

Recevez nos conseils tech et business directement dans votre boîte mail.

Suivez-nous