Mediator#
The Mediator pattern is a behavioral design pattern that lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
Key Points#
Reducing Complexity: The Mediator pattern is used to reduce the complexity of communication between multiple objects or classes. The pattern provides a mediator that handles all the communications between different classes.
Promoting Loose Coupling: The pattern promotes loose coupling by ensuring that instead of components referring to each other explicitly, their interaction is abstracted into this mediator.
Reusing Objects: The pattern allows you to reuse individual components more easily because they no longer depend on a large number of other components.
Centralizing Control: The pattern centralizes control. The mediator becomes the hub of communication, making it easier to understand the way objects interact and the potential paths of change.
Python Example#
from abc import ABC, abstractmethod
class Mediator(ABC):
@abstractmethod
def notify(self, sender: object, event: str) -> None:
pass
class ConcreteMediator(Mediator):
def __init__(self, component1: 'Component1', component2: 'Component2') -> None:
self._component1 = component1
self._component1.mediator = self
self._component2 = component2
self._component2.mediator = self
def notify(self, sender: object, event: str) -> None:
if event == "A":
print("Mediator reacts on A and triggers following operations:")
self._component2.do_c()
elif event == "D":
print("Mediator reacts on D and triggers following operations:")
self._component1.do_b()
self._component2.do_c()
class BaseComponent:
def __init__(self, mediator: Mediator = None) -> None:
self._mediator = mediator
@property
def mediator(self) -> Mediator:
return self._mediator
@mediator.setter
def mediator(self, mediator: Mediator) -> None:
self._mediator = mediator
class Component1(BaseComponent):
def do_a(self) -> None:
print("Component 1 does A.")
self.mediator.notify(self, "A")
def do_b(self) -> None:
print("Component 1 does B.")
self.mediator.notify(self, "B")
class Component2(BaseComponent):
def do_c(self) -> None:
print("Component 2 does C.")
self.mediator.notify(self, "C")
def do_d(self) -> None:
print("Component 2 does D.")
self.mediator.notify(self, "D")
Java Example#
public interface Mediator {
void notify(Component sender, String event);
}
public class ConcreteMediator implements Mediator {
private Component1 component1;
private Component2 component2;
public ConcreteMediator(Component1 component1, Component2 component2) {
this.component1 = component1;
this.component1.setMediator(this);
this.component2 = component2;
this.component2.setMediator(this);
}
@Override
public void notify(Component sender, String event) {
if (event.equals("A")) {
System.out.println("Mediator reacts on A and triggers following operations:");
this.component2.doC();
} else if (event.equals("D")) {
System.out.println("Mediator reacts on D and triggers following operations:");
this.component1.doB();
this.component2.doC();
}
}
}
public abstract class BaseComponent {
protected Mediator mediator;
public BaseComponent(Mediator mediator) {
this.mediator = mediator;
}
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
}
public class Component1 extends BaseComponent {
public Component1(Mediator mediator) {
super(mediator);
}
public void doA() {
System.out.println("Component 1 does A.");
mediator.notify(this, "A");
}
public void doB() {
System.out.println("Component 1 does B.");
mediator.notify(this, "B");
}
}
public class Component2 extends BaseComponent {
public Component2(Mediator mediator) {
super(mediator);
}
public void doC() {
System.out.println("Component 2 does C.");
mediator.notify(this, "C");
}
public void doD() {
System.out.println("Component 2 does D.");
mediator.notify(this, "D");
}
}
In these examples, ConcreteMediator knows and maintains relations between Component1 and Component2. Components only know about the Mediator interface and use it for communicating with other components. When a component changes its state, it notifies the mediator. Upon receiving the notification, the mediator may affect other components.