Home > GOF Pattern, java > GoF Patterns: Chain of Responsibility

GoF Patterns: Chain of Responsibility

6 aprile 2011

Translate in English with Google Translate
In questo articolo tratterò il pattern Chain of Responsibility

Motivazione

Si tratta di un pattern comportamentale basato su oggetti e viene utilizzato quando si ha la necessità di disaccoppiare il mittente di una richiesta dal destinatario.
Nel caso in cui il destinatario preveda che le richieste debbano essere gestite da una serie di attori ognuno dei quali con diversa responsabilità e tra loro collegati in modo gerarchico, siamo in presenza di una catena di responsabilità.
A fronte della ricezione di una richiesta, il destinatario gestirà la risposta propagando la richiesta nella catena fino ad individuare il responsabile. La gerarchia solitamente parte dal generale al particolare pertanto una richiesta destinata all’ultimo elemento della catena verrà propagata verso l’alto fino a raggiungere l’incaricato responsabile che avrà il compito di gestire/eseguire l’azione richiesta.
Il mittente non è tenuto a conoscere chi materialmente dovrà gestire/eseguire la richiesta, l’unica cosa che dovrà sapere è a chi dovrà inviare la richiesta. Sarà cura del destinatario organizzarsi in modo efficiente per recuperare il responsabile.
Pensiamo per esempio ad un call-center che deve gestire le richieste delle proprie utenze, qualora il personale non è in grado di risolvere il problema, propaga la richiesta al servizio di secondo livello che proverà a gestire/risolvere il problema altrimenti propaga a sua volta il problema.
In Java la propagazione delle eccezioni è un esempio di catena di responsabilità. Quando si verifica un errore, il gestore dell’errore, se non riesce a gestire l’eccezione in corso, propaga l’errore nella catena.

Partecipanti e Struttura
Questo pattern è composto dai seguenti partecipanti:

  1. Handler: definisce l’interfaccia per gestire le richieste, implementa il collegamento successivo alla gerarchia
  2. ConcreteHandler: gestisce le richieste per le quale è responsabile; può accedere al suo successore; se non è in grado di gestire la richiesta, la propaga al suo successore
  3. Client: inizia la richiesta ad un oggetto concreto che appartiene alla catena di responsabilità
Chain of Responsibility

Chain of Responsibility

Conseguenze

Tale pattern presenta i seguenti vantaggi/svantaggi:

  1. riduce l’accoppiamento: il richiedente deve solo sapere che la propria richiesta verrà gestita “adeguatamente”, non ha bisogno di sapere chi sarà realmente a gestire la richiesta.
  2. aggiungere flessibilità nell’assegnazione delle responsabilità degli oggetti: la catena della responsabilità può essere modificata senza condizionare il richiedente.
  3. risposta non garantita: la richiesta viene presa in carico e propagata nella gerarchia ma potrebbe non individuare il responsabile e non riuscire a dare una risposta. Oppure se la gerarchia delle responsabilità è errata, la richiesta non viene gestita.

Implementazione

Come esempio pensiamo alla gerarchia militare:

  • Ogni ufficiale conosce il proprio responsabile.
  • Ogni ufficiale svolge una funzione diversa
  • Ogni ufficiale ha uno stipendio diverso
  • Ogni ufficiale è collocato gerarchicamente in modo diverso

Vediamo una vista “semplificata” della gerarchia partendo dal Generale al Capitano:

Gerarchia Esercito

Gerarchia Esercito

Come esempio: pensiamo al caso in cui voglio sapere chi di loro soddisfa un determinato stipendio minimo. Faccio la domanda al ruolo più basso della mia catena, il Capitano, il quale se non soddisfa la richiesta propaga la domanda al suo responsabile: il Maggiore, e così via fino ad arrivare al Generale.

Vediamo come si presenta il pattern in UML in base all’esempio:

Examples Chain of Responsibility

Examples Chain of Responsibility

Creiamo la classe astratta Ufficiale che definisce:

  1. il metodo astratto check: che le classi dovranno implementare
  2. il metodo concreto setSuperiore : che le classi erediteranno ed utilizzeranno per impostare il diretto superiore
package patterns.chainOfResponsibility;

public abstract class Ufficiale {

    Ufficiale ufficiale = null;

    public void setSuperiore(Ufficiale ufficiale) {
        this.ufficiale = ufficiale;
    }

    public abstract void check(int stipendio);

}

Di seguito le classe figlie di Ufficiale che implementano il metodo astratto check ed ereditano il metodo concreto setSuperiore che definisce l’ufficiale superiore.

Di seguito la classe Capitano:

package patterns.chainOfResponsibility;

public class Capitano extends Ufficiale {

    @Override
    public void check(int stipendio) {
        if ( stipendio > 1000)
            ufficiale.check(stipendio);
        else
            System.out.println( "Li guadagna il " +this.getClass().getSimpleName() );
    }

}

Di seguito la classe Maggiore:

package patterns.chainOfResponsibility;

public class Maggiore extends Ufficiale {

    @Override
    public void check(int stipendio) {
        if ( stipendio > 2000)
            ufficiale.check(stipendio);
        else
            System.out.println( "Li guadagna il " +this.getClass().getSimpleName() );
    }

}

Di seguito la classe Tenente:

package patterns.chainOfResponsibility;

public class Tenente extends Ufficiale {

    @Override
    public void check(int stipendio) {
        if ( stipendio > 3000)
            ufficiale.check(stipendio);
        else
            System.out.println( "Li guadagna il " +this.getClass().getSimpleName() );
    }

}

Di seguito la classe Colonnello:

package patterns.chainOfResponsibility;

public class Colonnello extends Ufficiale {

    @Override
    public void check(int stipendio) {
        if ( stipendio > 4000)
            ufficiale.check(stipendio);
        else
            System.out.println( "Li guadagna il " +this.getClass().getSimpleName() );
    }

}

Di seguito la classe Generale:

package patterns.chainOfResponsibility;

public class Generale extends Ufficiale {

    @Override
    public void check(int stipendio) {
        if ( stipendio > 5000)
            System.out.println( "Stipendio troppo alto" );
        else
            System.out.println( "Li guadagna il " +this.getClass().getSimpleName() );
    }

}

Adesso costruisco la classe Client che crea le classi degli Ufficiali, poi crea la gerarchia militare ossia la catena di responsabilità ed infine invoca l’ultimo elemento della gerarchia cioè il Capitano, per ottenere la risposta dal Generale.
Vediamo come:

package patterns.chainOfResponsibility;

public class Client {

    public static void main(String[] args) {

        //Ufficiali
        Capitano capitano = new Capitano();
        Maggiore maggiore = new Maggiore();
        Tenente tenente = new Tenente();
        Colonnello colonnello = new Colonnello();
        Generale generale = new Generale();

        //creazione della gerarchia
        capitano.setSuperiore( maggiore );
        maggiore.setSuperiore( tenente );
        tenente.setSuperiore( colonnello );
        colonnello.setSuperiore( generale );

        System.out.println( "Chi guadagna almeno 4500 euro al mese ? ");
        capitano.check(4500);

    }

}

L’output del Client è il seguente:

$JAVA_HOME/bin/java patterns.chainOfResponsibility.Client
Chi guadagna almeno 4500 euro al mese ?
Li guadagna il Generale
Categorie:GOF Pattern, java
  1. 19 febbraio 2012 alle 5:18 PM

    Davvero un ottimo materiale…complimenti😀😀 Non ho trovato nulla sui pattern Template Method, Strategy, Observer e Visitor..non c’è possibilità di aggiungere qualcosa anche su questi? Grazie mille😀

    • 21 febbraio 2012 alle 5:05 PM

      grazie, mi fa molto piacere che ti siano utili.
      Per quanto riguarda gli altri pattern GOF invece conto di mettirli on-line quanto prima.

  1. No trackbacks yet.
I commenti sono chiusi.
%d blogger cliccano Mi Piace per questo: