Digital solutions
Design Patterns avec Laravel

Chain of Responsibility Pattern vs Pipeline Pattern

1. Chain of Responsibility Pattern

  • Objectif : Permet à plusieurs objets (handlers) de traiter une requête de manière séquentielle, chaque handler ayant la possibilité de la traiter ou de la passer au suivant.
  • Cas d'utilisation : Idéal pour des systèmes où plusieurs étapes indépendantes doivent traiter ou ignorer une requête, comme les middlewares dans Laravel.
  • Exemple : Gestion des exceptions dans une application Laravel, où chaque exception est traitée par un handler jusqu'à trouver celui qui peut gérer l'exception.

2. Pipeline Pattern

  • Objectif : Organiser une série d'opérations ou transformations successives sur des données, chaque étape recevant une entrée, la transformant, et la passant à l'étape suivante.
  • Cas d'utilisation : Utilisé pour les processus où chaque étape doit transformer ou modifier les données avant de passer à la suivante, comme dans les middlewares ou pour appliquer des transformations successives sur une commande.
  • Exemple : Traitement d'une commande dans une application Laravel où des étapes comme l'application de réductions, la vérification du stock, et le calcul des taxes sont exécutées successivement.

Comparaison directe :

Caractéristique Chain of Responsibility Pattern Pipeline Pattern
Traitement de la requête Chaque handler peut traiter ou passer la requête au suivant. Chaque étape transforme les données avant de les passer.
Séquence des étapes Séquentielle, mais certains handlers peuvent arrêter la chaîne. Toutes les étapes sont exécutées l'une après l'autre.
Utilisation principale Gestion des responsabilités comme les exceptions ou les erreurs. Transformation de données à travers plusieurs étapes successives.
Exemple Laravel Système de gestion des exceptions dans Handler.php. Application des middlewares HTTP ou traitement de commandes.

Exemples

Imaginons que nous traitions une requête d'utilisateur dans une application Laravel. La requête peut soit déclencher un traitement ou être transformée à travers plusieurs étapes :

1. Chain of Responsibility Pattern

La requête passe à travers plusieurs handlers, chacun ayant la possibilité de la traiter ou de la transmettre au suivant.

class ValidateRequestHandler {
    public function handle($request) {
        if (empty($request['email'])) {
            throw new Exception('Email is required');
        }
        // Pass to next handler
        return $next->handle($request);
    }
}

class AuthenticateHandler {
    public function handle($request) {
        if ($request['email'] !== 'user@example.com') {
            throw new Exception('User not authenticated');
        }
        // Pass to next handler
        return $next->handle($request);
    }
}

2. Pipeline Pattern

La requête est transformée à chaque étape, avec des opérations appliquées successivement.

class ApplyDiscount {
    public function handle($order, $next) {
        $order['total'] *= 0.9; // Apply 10% discount
        return $next($order);
    }
}

class CalculateTax {
    public function handle($order, $next) {
        $order['tax'] = $order['total'] * 0.15;
        $order['total'] += $order['tax'];
        return $next($order);
    }
}

Explications

  • Dans le Chain of Responsibility Pattern, chaque étape (handler) peut décider de traiter ou de passer la requête à la suivante. La chaîne peut s'arrêter à tout moment si une étape gère complètement la requête.

  • Dans le Pipeline Pattern, chaque étape modifie ou transforme les données avant de les passer à l'étape suivante, créant un flux continu de transformations sur les données jusqu'à la fin du pipeline.

Cas d'utilisation des patterns

  • Chain of Responsibility : Utile pour des systèmes où chaque étape peut ignorer ou traiter la requête. Par exemple, pour gérer des exceptions ou des autorisations.

  • Pipeline : Convient aux processus de transformation continue où chaque étape doit appliquer une opération ou une modification aux données, comme dans le traitement d'une commande ou les transformations de données.

Conclusion

Bien que les deux patterns soient comportementaux et se basent sur une exécution séquentielle, ils répondent à des besoins différents :

  • Le Chain of Responsibility Pattern permet à chaque étape de choisir si elle veut traiter ou passer la requête, tandis que le Pipeline Pattern garantit que chaque étape applique une transformation avant de passer les données.

  • Choisissez le Chain of Responsibility pour des systèmes qui doivent décider s'ils traitent ou non une requête. Optez pour le Pipeline Pattern lorsque plusieurs transformations doivent être appliquées successivement sur des données.