Learn the design pattern "Mediator" in Python

I would like to learn GoF design patterns in Python.

■ Mediator (mediator pattern)

The English word "Mediator" means "mediator". This pattern is a pattern that provides a simple and clear interface by making sure that the relationships between multiple objects that are intricately intertwined are processed through an "intermediary". In other words, the "Mediator" pattern plays the role of a "mediator" that receives inquiries from each of multiple objects under its jurisdiction, makes appropriate decisions, and gives instructions to all or part of the objects under its jurisdiction. It is a pattern that uses a class.

UML class and sequence diagram W3sDesign_Mediator_Design_Pattern_UML.jpg UML class diagram designpattern-mediator01.gif (The above is quoted from "Technical support site for IT engineers by IT Senka")

■ "Mediator" sample program

Actually, I would like to run a sample program that utilizes the Mediator pattern and check the following operation. Imagine a "user authentication screen" </ font> here.

--Suppose there is a user with username "hoge" and password "fuga" --** "login button" ** becomes active when username and password are entered -** Click "login button" ** to determine if user authentication was successful

In the sample program, by specifying the first argument: user name and the second argument: password, ", the user authentication screen" </ font> will be displayed with the user name. It is assumed that you have entered the password.

(Case 1) User authentication fails by specifying an incorrect password

The username was entered correctly, so ** "login button" ** was enabled, but username authentication failed.

$ python Main.py hoge huga
(Active login button)
(ID/PW is incorrect)
Login Failed!!

(Case 2) User authentication fails because the password was not specified.

** "login button" ** was not enabled and user authentication failed.

$ python Main.py hoge
Login Failed!!

(Case 3) User authentication succeeds by specifying the correct user name and password.

Since the user name was entered correctly, ** "login button" ** was enabled and user authentication was successful.

$ python Main.py hoge fuga
(Active login button)
(ID/PW is confirmed)
Login Succeed!!

With the above, the sample program worked as expected.

■ Details of sample program

Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Mediator

--Directory structure

.
├── Main.py
└── mediator
    ├── __init__.py
    ├── colleague.py
    └── mediator.py

(1) The role of Mediator (mediator, mediator)

The Mediator role communicates with the College role and defines the interface for making adjustments. In the sample program, the Mediator class serves this role.

mediator/mediator.py


from abc import ABCMeta, abstractmethod

class Mediator(metaclass=ABCMeta):
    @abstractmethod
    def on_change(self, component):
        pass

(2) The role of ConcreteMediator (concrete mediator, mediator)

The ConcreteMediator role implements the interface for the Mediator role and makes the actual adjustments. In the sample program, the ConcreteMediator class serves this role.

mediator/mediator.py


class ConcreteMediator(Mediator):
    def __init__(self):
        self.authentication = False

    def setColleagues(self, inputIdObj, inputPwObj, buttonObj):
        self.inputIdObj = inputIdObj
        self.inputPwObj = inputPwObj
        self.buttonObj = buttonObj

    def on_change(self, component):
        if component.name == "ID" or component.name == "PW":
            self.__refreshButton()
        elif component.name == "Login":
            self.__authentication()

    def __refreshButton(self):
        if self.inputIdObj.text is not None and self.inputPwObj.text is not None:
            print("(Active login button)")
            self.buttonObj.active = True

    def __authentication(self):
        if self.inputIdObj.text == "hoge" and self.inputPwObj.text == "fuga":
            print("(ID/PW is confirmed)")
            self.authentication = True
        else:
            print("(ID/PW is incorrect)")

(3) The role of Colleague

The Colleague role associates the Mediator role with the interface that communicates. In the sample program, the Colleague class serves this role.

mediator/colleague.py


from mediator.mediator import Mediator

class Colleague(Mediator):
    def __init__(self, mediatorObj, name):
        self.mediator = mediatorObj
        self.name = name

    def on_change(self):
        if self.mediator is not None:
            self.mediator.on_change(self)

(4) The role of Concrete College

The ConcreteColleague role is associated with the Colleague role. In the sample program, the ConcreteColleagueButton class and the ConcreteColleagueTextArea class serve this role.

mediator/colleague.py


class ConcreteColleagueButton(Colleague):
    def __init__(self, mediatorObj, name=None):
        super(ConcreteColleagueButton, self).__init__(mediatorObj, name)
        self.active = False

    def clickButton(self):
        if self.active:
            self.on_change()
        return self.mediator.authentication

    def checkButtonStatus(self):
        return self.active

class ConcreteColleagueTextArea(Colleague):
    def __init__(self, mediatorObj, name=None):
        super(ConcreteColleagueTextArea, self).__init__(mediatorObj, name)
        self.text = None

    def inputText(self, text):
        self.text = text
        self.on_change()

(5) The role of Client

In the sample program, the startMain method serves this role.

Main.py


import sys
from mediator.mediator import ConcreteMediator 
from mediator.colleague import ConcreteColleagueTextArea, ConcreteColleagueButton


def startMain(userid, password):
    m = ConcreteMediator()
    inputIdObj = ConcreteColleagueTextArea(m, "ID")
    inputPwObj = ConcreteColleagueTextArea(m, "PW")
    pushButtonObj = ConcreteColleagueButton(m, "Login")
    m.setColleagues(inputIdObj, inputPwObj, pushButtonObj)

    inputIdObj.inputText(userid)
    inputPwObj.inputText(password)
    if pushButtonObj.clickButton():
        print("Login Succeed!!")
    else:
        print("Login Failed!!")

def check_input_data(params):
    if len(params)==3:
        userid = params[1]
        password = params[2]
    elif len(params)==2:
        userid = params[1] 
        password = None
    elif len(params)==1:
        userid = None
        password = None
    return userid, password

if __name__ == "__main__":
    userid, password = check_input_data(sys.argv)
    startMain(userid, password)

■ Reference URL

-Design pattern in Python ~ Py design pattern ~ / Mediator pattern

Recommended Posts