Skip to content

Mediator Design Pattern

Video Lecture

Section Video Links
Mediator Overview Mediator Overview Mediator Overview Mediator Overview 
Mediator Use Case Mediator Use Case Mediator Use Case Mediator Use Case 

Overview

Objects communicate through the Mediator rather than directly with each other.

As a system evolves and becomes larger and supports more complex functionality and business rules, the problem of communicating between these components becomes more complicated to understand and manage. It may be beneficial to refactor your system to centralize some or all of its functionality via some kind of mediation process.

The mediator pattern is similar to implementing a Facade pattern between your objects and processes. Except that the structure of the Mediator allows multi directional communication between the objects or processes that would normally be interacting directly with each other.

While the Facade is a structural pattern, and the Mediator also implies structure in the way that it exists between two or more other objects or processes, it also allows changing the behavior of the interaction to make it more cooperative in some way. E.g., the centralization of application logic, managing the routing behavior, caching, logging, etc.

Terminology

  • Mediator: The coordinator of communications between the components (colleagues).
  • Colleagues: One of the many types of concrete components that use the mediator.

Mediator UML Diagram

Mediator Pattern UML Diagram

Source Code

...Refer to Book or Videos for extra content.

./mediator/mediator_concept.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# pylint: disable=too-few-public-methods
"Mediator Concept Sample Code"

class Mediator():
    "The Mediator Concrete Class"

    def __init__(self):
        self.colleague1 = Colleague1()
        self.colleague2 = Colleague2()

    def colleague1_method(self):
        "Calls the method provided by Colleague1"
        return self.colleague1.method_1()

    def colleague2_method(self):
        "Calls the method provided by Colleague2"
        return self.colleague2.method_2()

class Colleague1():
    "This Colleague provides data for Colleague2"

    @staticmethod
    def method_1():
        "A simple method"
        return "Here is the Colleague1 specific data you asked for"

class Colleague2():
    "This Colleague provides data for Colleague1"

    @staticmethod
    def method_2():
        "A simple method"
        return "Here is the Colleague2 specific data you asked for"

# The Client
MEDIATOR = Mediator()

# Colleague1 wants some data from Colleague2
DATA = MEDIATOR.colleague2_method()
print(f"COLLEAGUE1 <--> {DATA}")

# Colleague2 wants some data from Colleague1
DATA = MEDIATOR.colleague1_method()
print(f"COLLEAGUE2 <--> {DATA}")

Output

1
2
3
python ./mediator/mediator_concept.py    
COLLEAGUE1 <--> Here is the Colleague2 specific data you asked for
COLLEAGUE2 <--> Here is the Colleague1 specific data you asked for

Example Use Case

...Refer to Book or Videos for extra content.

Example UML Diagram

Mediator Pattern UML Diagram

Source Code

./mediator/client.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
"The Mediator Use Case Example"
from component import Component
from mediator import Mediator

MEDIATOR = Mediator()
COMPONENT1 = Component(MEDIATOR, "Component1")
COMPONENT2 = Component(MEDIATOR, "Component2")
COMPONENT3 = Component(MEDIATOR, "Component3")
MEDIATOR.add(COMPONENT1)
MEDIATOR.add(COMPONENT2)
MEDIATOR.add(COMPONENT3)

COMPONENT1.notify("data A")
COMPONENT2.notify("data B")
COMPONENT3.notify("data C")

./mediator/component.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
"Each component stays synchronized through a mediator"
from interface_component import IComponent

class Component(IComponent):
    "Each component stays synchronized through a mediator"

    def __init__(self, mediator, name):
        self._mediator = mediator
        self._name = name

    def notify(self, message):
        print(self._name + ": >>> Out >>> : " + message)
        self._mediator.notify(message, self)

    def receive(self, message):
        print(self._name + ": <<< In <<< : " + message)

./mediator/interface_component.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
"An interface that each component will implement"
from abc import ABCMeta, abstractmethod

class IComponent(metaclass=ABCMeta):
    "An interface that each component will implement"

    @staticmethod
    @abstractmethod
    def notify(message):
        "The required notify method"

    @staticmethod
    @abstractmethod
    def receive(message):
        "The required receive method"

./mediator/mediator.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
"The Subject that all components will stay synchronized with"


class Mediator():
    "A Subject whose notify method is mediated"

    def __init__(self):
        self._components = set()

    def add(self, component):
        "Add components"
        self._components.add(component)

    def notify(self, message, originator):
        "Add components except for the originator component"
        for component in self._components:
            if component != originator:
                component.receive(message)

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
python ./mediator/client.py
Component1: >>> Out >>> : data A
Component2: <<< In <<< : data A
Component3: <<< In <<< : data A
Component2: >>> Out >>> : data B
Component3: <<< In <<< : data B
Component1: <<< In <<< : data B
Component3: >>> Out >>> : data C
Component2: <<< In <<< : data C
Component1: <<< In <<< : data C

Summary

...Refer to Book or Videos for extra content.