Chain of Responsability
(Chaîne de responsabilité)

But : Découpler l'émetteur d'une requête du receveur en permettant à plus d'un objet de gérer la requête.
Faire un chaîne de receveurs, et passer la requête à la chaîne jusqu'à ce qu'un receveur gère la requête.

Structure

Ce pattern fournit un mécanisme assez simple qui permet de fabriquer la "chaîne".
Le mécanisme est basé sur une abstraction (Handler) contenant une méthode (handleRequest()), ainsi qu'un champ successor Chain of responsability - structure

Exemples

Exemple GOF

Cas de la gestion du clic droit de la souris pour gérer un menu contextuel d'aide.
Le pattern peut être utilisé pour transmettre la requête, en allant toujours du particulier au général.
Par exemple, si on fait un clic droit sur un bouton : si le bouton a une aide spécifique, elle va être affichée, sinon il passe la requête à son conteneur, qui refait la même chose. Chain of responsability - exemple La requête est passée d'un maillon à l'autre de la chaîne jusqu'à ce qu'elle soit gérée (ou pas). Chain of responsability - séquence

Exemple wikipedia

Code dans WikipediaDemo.java

Système de validation de dépenses au sein d'une entreprise où différentes personnes sont habilitées à valider certaines sommes maximales.

L'abstraction PurchasePower représente une telle personne :
// ======= Abstract handler =======
abstract class PurchasePower {
    protected static final double BASE = 100;
    protected PurchasePower successor;

    abstract protected double getAllowable();
    abstract protected String getRole();

    public void setSuccessor(PurchasePower successor) {
        this.successor = successor;
    }

    public void handleRequest(PurchaseRequest request) {
        if (request.getAmount() < this.getAllowable()) {
            System.out.println(request.getAmount() + " $ approved by " + this.getRole());
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}
Chaque handler concret représente un acteur particulier :
// ======= Concrete handlers =======
class Manager extends PurchasePower {
    protected double getAllowable() { return BASE * 10; }
    protected String getRole() { return "Manager"; }
}

class Director extends PurchasePower {
    protected double getAllowable() { return BASE * 20; }
    protected String getRole() { return "Director"; }
}

// ...
Le client instancie les différents acteurs et créé la chaîne :
public class WikipediaDemo {

    // ======= Client =======
    public static void main(String[] args) {
        
        // create chain of responsability
        Manager manager = new Manager();
        Director director = new Director();
        VicePresident vp = new VicePresident();
        President president = new President();
        Nobody nobody = new Nobody();
        
        manager.setSuccessor(director);
        director.setSuccessor(vp);
        vp.setSuccessor(president);
        president.setSuccessor(nobody);

        // ...
        
        try {
            while (true) {
                System.out.println("\nEnter the amount to check who should approve your expenditure.");
                System.out.print("> ");
                double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine());
                manager.handleRequest(new PurchaseRequest(d));
            }
        }
        catch (Exception e) {
            System.exit(1);
        }
    }
}
Bien remarquer que la chaîne est organisée du "plus petit au plus grand", et que lorsqu'on appelle handleRequest(), on l'appelle sur le "plus petit".

Remarques