Mediator Pattern

 Introduction:

Mediator pattern is behavioral design pattern. It decouples the object by introducing new layer in between the objects, and objects interacts with each other through this new layer. If objects directs directly with early, system components becomes tightly coupled with each other, and its hard to make as reusable components, and extending, maintaining it becomes difficult. 

Mediator pattern introduce a new object with encapsulates how a set of objects interact. Objects doesn't interact directly, it communicates through mediator object. This promotes the loose coupling between the objects, that helps to vary the objects independently. 

When to use, 

  • When we can't alter (extend ) any class because its closed coupled with other classes.
  • When can't reuse any class in other application since its tightly coupled with other classes. 
Mediator pattern creates a new object which encapsulates how other object has to interact with each other. Objects interacts with mediator pattern through the mediator object. This creates a loose coupling between the objects, and it can extended or alter independently since its not directly communicating with each other.

How to use, 

  1. Identify a collection of interacting objects that would benefit from mutual decoupling.
  2. Encapsulate those interactions in the abstraction of a new class.
  3. Create an instance of that new class and rework all "peer" objects to interact with the Mediator only.
  4. Balance the principle of decoupling with the principle of distributing responsibility evenly.
  5. Be careful not to create a "controller" or "god" object.

UML diagram:











Classic example of mediator pattern is air traffic controller system.

Implementation:

Sourcecode:https://github.com/krishnaKSA/design_patterns_cplusplus/blob/main/MediatorPattern/MediatorPattern.hpp

Class diagram:
















Basecomponent:

This class contains IMediator class object which will be used by the subclasses.

  class IBaseComponent
    {
        protected:
        IMediator* mediator;
        public:
        IBaseComponent()
        {
           this->mediator = nullptr;
        }
        void setMediator(IMediator* mediator) {
           this->mediator = mediator;
        }
    };

Mediator interface class:

//Mediator Interface
    class IMediator
    {
        public:
        virtual void action() = 0;
        virtual void start(bool value) = 0;
    };

Derived classes from Basecomponents:

These classes interact with each other through the mediator class.  

    //Button class
    class Button : public IBaseComponent
    {
        private:
        public:
        void press()
        {
            mediator->action();
        }
    };
    //Fan class
    class Fan : public IBaseComponent
    {
        private:
        bool turnOn;
        public:
        Fan()
        {
            turnOn = false;
        }
        void turnOnOROff()
        {
            if(!turnOn)
            {
                cout<<"FAN: turn ON"<<endl;
                turnOn = true;
            }
            else
            {
                cout<<"FAN: turn OFF"<<endl;
                turnOn = false;
            }
            if(mediator)
            {
                mediator->start(turnOn);
            }
        }

    };
    //PowerSupply class
    class PowerSupply: public IBaseComponent
    {
        private:
        bool turnOn;
        public:
        PowerSupply()
        {
            turnOn = false;
        }
        void turnOnOROff(bool value)
        {
            if(value)
            {
                cout<<"PowerSupply: turn ON"<<endl;
                turnOn = true;
            }
            else
            {
                cout<<"PowerSupply: turn OFF"<<endl;
                turnOn = false;
            }
        }
       

    };

Mediator class:

Mediator class contains the objects of the classes which has to interact through mediator object.
    //Mediator class
    class Mediator:public IMediator
    {
        private:
        Button* button;
        Fan* fan;
        PowerSupply* power;

        public:
        Mediator(Button* button,  Fan* fan, PowerSupply* power)
        {
            this->button = button;
            this->fan = fan;
            this->power = power;
            this->button->setMediator(this);
            this->fan->setMediator(this);
            this->power->setMediator(this);
        }
        void action() override
        {
            fan->turnOnOROff();
        }
        void start(bool value) override
        {
            power->turnOnOROff(value);
        }
    };

Client code:

    //client code
    void testClientCode()
    {
       
        Button* button  = new Button;
        Fan* fan = new Fan;
        PowerSupply* power = new PowerSupply;
        IMediator* mediator = new Mediator(button, fan, power);
        button->setMediator(mediator);
        fan->setMediator(mediator);
        power->setMediator(mediator);
        button->press();
        button->press();
       
    }