Python Mediator Design Pattern

1. Definition

The Mediator Design Pattern defines an object that encapsulates how a set of objects interact. This pattern promotes loose coupling by keeping objects from referring to each other explicitly, letting you vary their interaction independently.

2. Problem Statement

In a system where multiple components need to communicate with each other, direct communication can lead to high coupling. This makes the system harder to maintain and extend, as changes in one component might affect many others.

3. Solution

Use a mediator object to centralize external communications between components. This way, components only need to know about the mediator, reducing the dependencies between them.

4. Real-World Use Cases

1. Air traffic control coordinating the movement of planes.

2. Chat rooms where a central system handles messages between participants.

3. GUI libraries where components like buttons and text fields communicate through a central dialog.

5. Implementation Steps

1. Define a Mediator interface that will communicate with the Colleague objects.

2. Implement the ConcreteMediator class that will coordinate the Colleague objects.

3. Colleague classes should have a reference to the mediator but not to other colleagues.

6. Implementation in Python

# Mediator interface
class Mediator:
    def notify(self, sender, event):
        pass
# ConcreteMediator
class ConcreteMediator(Mediator):
    def __init__(self):
        self._colleague1 = Colleague1(self)
        self._colleague2 = Colleague2(self)
    def notify(self, sender, event):
        if sender == self._colleague1 and event == "A":
            self._colleague2.react_on_a()
        elif sender == self._colleague2 and event == "B":
            self._colleague1.react_on_b()
# Base Colleague
class BaseColleague:
    def __init__(self, mediator):
        self._mediator = mediator
# Colleague1
class Colleague1(BaseColleague):
    def do_a(self):
        print("Colleague1 triggers event A.")
        self._mediator.notify(self, "A")
    def react_on_b(self):
        print("Colleague1 reacts on event B.")
# Colleague2
class Colleague2(BaseColleague):
    def do_b(self):
        print("Colleague2 triggers event B.")
        self._mediator.notify(self, "B")
    def react_on_a(self):
        print("Colleague2 reacts on event A.")
# Client code
mediator = ConcreteMediator()
mediator._colleague1.do_a()
mediator._colleague2.do_b()

Output:

Colleague1 triggers event A.
Colleague2 reacts on event A.
Colleague2 triggers event B.
Colleague1 reacts on event B.

Explanation:

1. A Mediator interface is defined with a notify method to communicate with Colleague objects.

2. ConcreteMediator implements this interface and handles the coordination between specific colleagues.

3. Colleague classes (Colleague1 and Colleague2) use the mediator to communicate with other colleagues. When an event is triggered in one colleague, it notifies the mediator, which then tells the other colleague to react accordingly.

4. The client code demonstrates how triggering an event in one colleague leads to a reaction in another colleague, facilitated by the mediator.

7. When to use?

Use the Mediator Pattern when:

1. A set of objects communicate in well-defined but complex ways, and you want to reuse these objects independently.

2. You want to reduce subclassing by localizing external communications in one class.

3. You want to centralize control and make it easier to maintain the interactions between components.


Comments