Home > GOF Pattern, java > GoF Patterns: Mediator

GoF Patterns: Mediator

2 dicembre 2011

Translate in English with Google Translate
In questo articolo tratterò il pattern Mediator

Motivazione

Si tratta di un pattern comportamentale basato su oggetti e viene utilizzato per permettere lo scambio di messaggi tra diversi attori tramite un intermediario. In questo modo gli attori sono collegati indirettamente tramite un intermediario. Disaccoppiare gli attori consente di gestire meglio una serie di problematiche come: centralizzazione delle connessioni, modifiche più rapide, semplificazione dei protocolli.

Nel gergo del pattern Mediator usiamo il termine Colleghi per indicare gli attori.
Per capire meglio questo problema facciamo riferimento alle reti di computer. Infatti la modalità di comunicazione è alla base delle topologie di reti. Una rete basata su “fully connected network” tutti i computer risultano connessi tra di loro. Nel nostro caso tutti i nostri Colleghi risultano connessi direttamente tra di loro ma questo comporta la relizzazione di una intricata rete di comunicazione, come mostrato di seguito:

Complessa rete di comunicazione

Complessa rete di comunicazione

Un’altra tipologia di rete è “star network” in cui tutti computer risultano connessi ad un server intermediario che agisce da centro stella, da qui il nome, che rappresenta l’anello di collegamento di tutti i server presenti nella rete. Questo è il caso in cui i nostri Colleghi si connettono solo al Mediatore che si interpone tra tutte le comunicazioni. Vediamo come il grafico delle connessioni in questo caso è altamento semplificato.

Rete semplificata tramite un Mediatore

Rete semplificata tramite un Mediatore

Partecipanti e Struttura

Questo pattern è composto dai seguenti partecipanti:

  • Mediator: definisce una interfaccia per comunicare con i Colleague
  • ConcreateMediator: mantiene la lista dei colleghi e implementa lo scambio di messaggi tra di loro
  • Colleague: definisce l’interfaccia dei Colleague
  • ConcreateColleague: implementa il singole collega e le modalità di comunicazione con il Mediator
Mediator Pattern

Mediator Pattern

Conseguenze

Tale pattern presenta i seguenti vantaggi/svantaggi:

  • Disaccoppiare i colleghi: i colleghi dialogano tra di loro iin modo indiretto passando per il Mediatore e questo facilita la gestione delle comunicazioni
  • Semplificare le connessioni: il Mediatore consente di ridurre le connessioni dei Colleghi da many-to-many a one-to-many
  • Controllo centralizzato: il controllo delle comunicazioni è centralizzato e questo consente di avere una visione complessiva del sistema ed una gestione più efficente delle modifiche
  • Single Point of Failure: nel caso di malfunzionamento del Mediatore l’intero sistema sarà coinvolto ed in caso di fermo del Mediatore, i Colleghi resteranno isolati

Implementazione

Come esempio pensiamo al caso in cui 2 Colleghi debbano comunicare tra di loro tramite l’ausilio di un Mediatore.

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

Mediator Pattern Esempio

Mediator Pattern Esempio

Definiamo il Mediatore che definisce le modalità di inserimento nella lista dei Colleghi e le interazioni tra i Colleghi:

package patterns.mediator;

public abstract class Mediatore {

   public abstract void aggiungi(Collega collega);

   public abstract void inviaRicevi(String nickNameMittente, String messaggio, String nickNameDestinatario);

}

L’implementazione del Mediatore consente di aggiungere i Colleghi nella lista tramite il metodo aggiungi, volendo è possibile prevedere anche la loro rimozione, e intermedia i messaggi da scambiare tramite il metodo inviaRiceve:

package patterns.mediator;

import java.util.ArrayList;
import java.util.List;

public class ConcretoMediatore extends Mediatore {

    private List<Collega> colleghiInLista = new ArrayList<Collega>();

    @Override
    public void aggiungi(Collega collega) {
        colleghiInLista.add(collega);
    }

    @Override
    public void inviaRicevi(String nickNameMittente, String messaggio, String nickNameDestinatario) {
        for(Collega collegaInLista: colleghiInLista){
            if( collegaInLista.getNickName().equals(nickNameDestinatario) ){
                collegaInLista.ricevi(messaggio, nickNameMittente);
            }
        }
    }
    
}

Vediamo come si presenta la classe Collega che gestisce i metodi di invio e ricezione dei messaggi, da e verso il Collega verso cui si scambia il messaggio.

package patterns.mediator;

public abstract class Collega {

    public abstract void invia(String messaggio, String nickNameDestinatario);
    
    public abstract String getNickName();
    
    public abstract void ricevi(String messaggio, String nickNameMittente);
    
}

Vediamo un esempio di un Collega che implementa i metodi invia e riceve:

  • in sede di ricezione: stampa semplicemente il testo ed il mittente
  • in sede di invio: interpone il mediatore per inviare il messaggio al Collega
package patterns.mediator;

public class CollegaA extends Collega {

    private String nickName;
    private Mediatore mediatore;
    
    public CollegaA(Mediatore mediatore, String nickName) {
        this.mediatore = mediatore;
        this.nickName = nickName;
        
        this.mediatore.aggiungi(this);
    }
    
    @Override
    public void invia(String messaggio, String nickNameDestinatario) {
        mediatore.inviaRicevi(nickName, messaggio, nickNameDestinatario);
    }

    @Override
    public String getNickName() {
        return this.nickName;
    }

    @Override
    public void ricevi(String messaggio, String nickNameMittente) {
        System.out.println(nickNameMittente + " -> " + nickName + ": " + messaggio );
    }
}

Idem per il Collega B:

package patterns.mediator;

public class CollegaB extends Collega {
    
    private String nickName;
    private Mediatore mediatore;
    
    public CollegaB(Mediatore mediatore, String nickName) {
        this.mediatore = mediatore;
        this.nickName = nickName;
        
        this.mediatore.aggiungi(this);
    }

    @Override
    public void invia(String messaggio, String nickNameDestinatario) {
        mediatore.inviaRicevi(nickName, messaggio, nickNameDestinatario);
    }

    @Override
    public String getNickName() {
        return this.nickName;
    }

    @Override
    public void ricevi(String messaggio, String nickNameMittente) {
        System.out.println(nickNameMittente + " -> " + nickName + ": " + messaggio );
        
    }
}

Vediamo la classe Client che si occupa di creare le reference al Mediatore, al CollegaA, al CollegaB e di scambiare dei messaggi tra di loro.

package patterns.mediator;

public class Client {
    public static void main(String[] args) {
        
        Mediatore mediatore = new ConcretoMediatore();
        
        Collega collegaA = new CollegaA( mediatore, "Andrea" );
        Collega collegaB = new CollegaB( mediatore, "Giovanni" );
        
        collegaA.invia("Ciao, come stai? ", "Giovanni");
        collegaB.invia("Tutto bene, e tu?", "Andrea");
        collegaA.invia("Tutto bene, si programma!", "Giovanni");

    }
}

Il risultato dell’esecuzione mostra i messaggi scambiati tramite l’ausilio del Mediatore:

$JAVA_HOME/bin/java patterns.mediator.Client
Andrea -> Giovanni: Ciao, come stai?
Giovanni -> Andrea: Tutto bene, e tu?
Andrea -> Giovanni: Tutto bene, si programma!
Categorie:GOF Pattern, java
  1. fab
    6 dicembre 2012 alle 10:40 AM

    ArrayList isn’t of any use here. This description is at least incomplete.

    • 17 marzo 2013 alle 5:22 PM

      You are right, I completed the example.
      I’m sorry for the delay in replying.

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