Z życia wzięte …
„… centralny magazyn firmy, przychodzą do niego materiały, narzędzia, półfabrykaty. Jako jedyny zna adresy poszczególnych oddziałów i osoby odpowiedzialne za przepływ materiałów w danym oddziale. Jego sprawne działanie ma wpływ na bezproblemowe wytwarzanie produktów firmy. Po co taki centralny magazyn, nie lepiej żeby poszczególne działy kontaktowały się ze sobą? A jednak nie, taki centralny dział który jako jedyny wie o innych, zaprowadza porządek w chaosie. …”

Mediator – czynnościowy wzorzec projektowy, który:

  • Jako jedyny zna większość współpracujących ze sobą obiektów
  • Zapewnia zmniejszenie ilości powiązań pomiędzy klasami
  • Daje jednolity interfejs do przesyłania komunikatów pomiędzy klasami

Mediator jest podobny w działaniu do wzorca obserwatora, lecz występują różnice: obserwator zna wszystkie obiekty do których jest wysyłany komunikat, mediator – hermetyzuje to połączenia, obiekt nadający zna tylko mediatora, żadnego innego obiektu

Zalety:

  • Luźna zależność pomiędzy obiektami w systemie – nadawca komunikatu -> mediator -> odbiorca lub odbiorcy komunikatów
  • Relacja pomiędzy tymi obiektami jest dynamiczna, jest możliwe dodanie nowych opcji w trakcie działania systemu
  • Możliwość ograniczenia korzystania z poszczególnych elementów systemu, wystarczy odłączyć danego odbiorcę komunikatów lub nadawcę komunikatów

Wady:

  • Możliwość zapętlenia się aplikacji w przypadku gdy jeden obiekt jest równocześnie odbiorcą i nadawcą komunikatów. Na skutek odebrania komunikatu obiekt zmienia swój stan i nadaje nowy komunikat. W tym przypadku grozi nam zapętlenie się kolejki komunikatów.

Przykładowa implementacja (Java):

 
package pl.shad.net.blog;
 
import java.util.ArrayList;
 
/**
 * Definicja interfejsu mediatora
 */
interface Mediator{
	void sendMessage(String message);
}
 
/**
 * Klasa implementująca interfejs mediatora,
 * jako jednyna zna wszystkie obiekty robocze
 */
class MediatorHub implements Mediator{
 
	private ArrayList< JobWorker > jobWorkers = new ArrayList< JobWorker >();
 
	/**
	 * Dodanie obiektu do obsługi komunikatów
	 * @param jobWorker
	 */
	public void addJobWorker(JobWorker jobWorker){
		jobWorkers.add(jobWorker);
	}
 
	/**
	 * Usunięcie obiektu z obsługi komunikatów
	 * @param jobWorker
	 */
	public void removeJobWorker(JobWorker jobWorker){
		jobWorkers.remove(jobWorker);
	}
 
	/**
	 * Wysłanie komunikatu do współpracujących obiektów
	 * @param message
	 */
	@Override
	public void sendMessage(String message){
		for (JobWorker jobWorker : jobWorkers){
			jobWorker.receiveMessage(message);
		}
	}
}
 
/**
 * Klasa definująca obiekt wysyłający komunikaty do mediatora
 * i odbirający komunikaty od mediatora
 */
class JobWorker{
 
	private String name;
	private Mediator mediator;
 
	public JobWorker(String name, Mediator mediator){
		this.name = name;
		this.mediator = mediator;
	}
 
	/**
	 * Wysłanie komunikatu
	 */
	public void sendMessage(){
		this.mediator.sendMessage(name + " send msg");
	}
 
	/**
	 * Odebranie komunikatu
	 * @param message
	 */
	public void receiveMessage(String message){
		System.out.println("Message -> msg: '" + message + "' to: " + name);
	}
}
 
/**
 * Uruchomieniowa klasa testująca
 */
public class DesignPatternsMediator{
	public static void main(String[] args){
 
		//
		// Utworzenie obiektów oraz stworzenie dynamicznych powiązań
		//
		MediatorHub mediatorHub = new MediatorHub();
 
		JobWorker job1 = new JobWorker("Job1", mediatorHub);
		JobWorker job2 = new JobWorker("Job2", mediatorHub);
		JobWorker job3 = new JobWorker("Job3", mediatorHub);
		JobWorker job4 = new JobWorker("Job4", mediatorHub);
 
		mediatorHub.addJobWorker(job1);
		mediatorHub.addJobWorker(job2);
		mediatorHub.addJobWorker(job3);
		mediatorHub.addJobWorker(job4);
 
		//
		// Wysłanie komunikatu od obiektu1 do wszytkch obiektów roboczych
		//
		job1.sendMessage();
 
		//
		// Wysłanie komunikatu od obiektu2 do wszytkch obiektów roboczych
		// poza obiektem2
		//
		mediatorHub.removeJobWorker(job2);
		job2.sendMessage();
	}
}