Mediator Pattern

The Mediator Pattern is a behavioral design pattern that promotes loose coupling between objects by introducing a mediator object.

The mediator acts as a central hub, allowing objects to communicate with each other without knowing each other’s specific details. Instead of objects communicating directly, they communicate through the mediator, which handles the interactions between them.

Mediator Pattern Example:

Think of an air traffic control tower as an analogy for the Mediator Pattern. The tower acts as a mediator between different aircraft. Instead of planes communicating directly with each other, they communicate with the air traffic control tower, which manages their movements and ensures safe navigation.

Mediator Pattern C++ Example:

Sure! Let’s use a different example to explain the Mediator Pattern. Consider a smart home system where various smart devices need to communicate and coordinate with each other. The Mediator Pattern can be used to handle interactions among these devices.

Mediator Pattern C++ Code:

#include <iostream>
#include <string>
#include <vector>

// Forward declaration
class SmartDevice;

// Mediator Interface
class SmartHomeMediator {
public:
    virtual void sendMessage(const std::string& message, const SmartDevice* sender) const = 0;
};

// Concrete Mediator: SmartHome
class SmartHome : public SmartHomeMediator {
private:
    std::vector<SmartDevice*> devices;

public:
    void addDevice(SmartDevice* device) {
        devices.push_back(device);
    }

    void sendMessage(const std::string& message, const SmartDevice* sender) const override {
        for (SmartDevice* device : devices) {
            if (device != sender) {
                device->receiveMessage(message);
            }
        }
    }
};

// Colleague Interface
class SmartDevice {
protected:
    SmartHomeMediator* smartHome;

public:
    SmartDevice(SmartHomeMediator* smartHome) : smartHome(smartHome) {}

    virtual void sendMessage(const std::string& message) const {
        smartHome->sendMessage(message, this);
    }

    virtual void receiveMessage(const std::string& message) const = 0;
};

// Concrete Colleague: Light
class Light : public SmartDevice {
public:
    Light(SmartHomeMediator* smartHome) : SmartDevice(smartHome) {}

    void receiveMessage(const std::string& message) const override {
        std::cout << "Light received message: " << message << std::endl;
    }
};

// Concrete Colleague: Thermostat
class Thermostat : public SmartDevice {
public:
    Thermostat(SmartHomeMediator* smartHome) : SmartDevice(smartHome) {}

    void receiveMessage(const std::string& message) const override {
        std::cout << "Thermostat received message: " << message << std::endl;
    }
};

int main() {
    SmartHome smartHome;
    Light light(&smartHome);
    Thermostat thermostat(&smartHome);

    smartHome.addDevice(&light);
    smartHome.addDevice(&thermostat);

    light.sendMessage("Turn on the lights!");
    thermostat.sendMessage("Set temperature to 25C");

    return 0;
}

Output:

Thermostat received message: Turn on the lights!
Light received message: Set temperature to 25C

Mediator Pattern Explanation of the Code:


In this example, we have four main components:

  1. SmartHomeMediator is the mediator interface that declares the method sendMessage.
  2. SmartHome is the concrete mediator that implements the sendMessage method to relay messages to all smart devices except the sender.
  3. SmartDevice is the colleague interface (also known as the colleague class) that declares the method sendMessage and receiveMessage.
  4. Light and Thermostat are concrete colleagues that extend SmartDevice and implement the receiveMessage method to handle received messages.

In the main function, we create a SmartHome as the mediator and two smart devices: light and thermostat. Smart devices communicate with each other by sending messages through the smart home (mediator). When a device sends a message, the smart home relays it to all other devices except the sender.

Applications of Mediator Pattern:

  1. GUI frameworks: It can be used to handle communication between different GUI components, such as buttons, text fields, and menus, in a user interface.
  2. Multiplayer games: In online games, the Mediator Pattern can facilitate communication between different players or game objects.
  3. Air traffic control systems: As mentioned before, it can be used to manage communications between different aircraft and air traffic control centers.

Mediator Pattern Pros and Cons:

Mediator Pattern Pros:

  • Decouples components: The Mediator Pattern reduces direct dependencies between objects, promoting loose coupling.
  • Centralized control: It allows centralized control over communication and behavior between objects, making the system easier to maintain.
  • Simplifies communication: The pattern simplifies complex communication logic by encapsulating it in the mediator.

Mediator Pattern Cons:

  • Complexity: Introducing a mediator can add complexity to the system, especially for simple scenarios where direct communication is sufficient.
  • Single point of failure: The mediator can become a single point of failure if it malfunctions, affecting communication between components.
  • Performance overhead: The pattern may introduce some performance overhead due to the additional level of indirection and message routing. However, this overhead is usually negligible in most scenarios.