Saturday, August 19, 2023

Mediator Design Pattern in Python...

This design pattern 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.

The Mediator interface declares a method used by components to notify the mediator about various events. The Mediator may react to these events and triggers specific components to execute different yet specific tasks.

The Base Component provides the basic functionality of storing a mediator's reference inside the component.

Concrete Components implement various functionality. They don't depend on other components.

Let me explain it to you with an example.

Suppose two students Ridit and Rajdeep take a lot of responsibility in a class. But something bad happens between them, and hence they don't talk to each other. So, here comes the ClassMonitor - as a Mediator between Rajdeep and Ridit - if Ridit does anything that needs Rajdeep to do another task, Ridit notifies the Class Monitor, and then the Class Monitor asks Rajdeep to execute the necessary task.

Here's the class diagram of the Mediator Pattern

There are many uses for this design pattern. This design pattern can be found in most of the widget message-passing systems - individual widgets don't pass or communicate with each other - but they communicate through the container window.

For Android engineers - you remember how two fragments talk to each other through the container window.

Here goes the source code for this Design Pattern.

Enjoy.

Happy learning.

from abc import ABC, abstractmethod

class ClassMonitor(ABC):
@abstractmethod
def notify(self, sender, event):
pass
class ConcreteClassMonitor(ClassMonitor):
def __init__(self, student1, student2):
self.student1 = student1
self.student2 = student2

def notify(self, sender, event):
if event == "A":
print("The class Monitor reacts to event A and triggers Rajdeep to do task C")
self.student2.do_c()
elif event == "D":
print("The class Monitor reacts to event D and triggers Ridit to do Task B and Rajdeep to do Task C")
self.student1.do_b()
self.student2.do_c()

class BaseStudent:
def __init__(self, monitor):
self._monitor = monitor

def getMonitorr(self):
return self._monitor
def setMonitor(self, monitor):
self._monitor = monitor

class Ridit(BaseStudent):
def do_a(self):
print("Ridit does A.")
self._monitor.notify(self, "A")

def do_b(self):
print("Ridit does B.")
self._monitor.notify(self, "B")

class Rajdeep(BaseStudent):
def do_c(self):
print("Rajdeep does C.")
self._monitor.notify(self, "C")

def do_d(self):
print("Rajdeep does D")
self._monitor.notify(self, "D")

if __name__ == '__main__':
ridit = Ridit(None)
rajdeep = Rajdeep(None)
classMonitor = ConcreteClassMonitor(ridit,rajdeep)
ridit.setMonitor(classMonitor)
rajdeep.setMonitor(classMonitor)

print("Ma'am asks Ridit to do A")
ridit.do_a()

print("Ma'am asks Rajdeep to do D.")
rajdeep.do_d()
If we run the above program the output will be like the following:


Ma'am asks Ridit to do A
Ridit does A.
The class Monitor reacts to event A and triggers Rajdeep to do task C
Rajdeep does C.
Ma'am asks Rajdeep to do  D.
Rajdeep does D
The class Monitor reacts to event D and triggers Ridit to do Task B and Rajdeep to do Task C
Ridit does B.
Rajdeep does C.


No comments: