C++ Mediator Pattern Example

1. Definition

The Mediator Design Pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by ensuring that instead of objects referring to each other explicitly, their interaction is abstracted through a mediator object.

2. Problem Statement

In a system composed of multiple objects, interactions between these objects can lead to a system that's hard to understand, maintain, and scale. Direct communication between objects can lead to tight coupling which can be problematic.

3. Solution

Centralize external communications between objects into a mediator object. This mediator object handles the interaction logic and objects in the system only communicate with the mediator rather than each other.

4. Real-World Use Cases

1. Air traffic control room managing flights.

2. Chat rooms where a centralized server handles messages and users only interact through this server.

3. GUI libraries, where the dialog box is a mediator between GUI components.

5. Implementation Steps

1. Create the Mediator interface that defines the communication from Colleague objects.

2. Implement ConcreteMediator that contains the logic for the communication between different colleagues.

3. Define Colleague classes which will interact with each other through the mediator.

6. Implementation in C++

// Step 1: Mediator Interface
class Mediator {
public:
    virtual ~Mediator() {}
    virtual void send(const std::string& message, class Colleague* colleague) = 0;
};
// Step 2: ConcreteMediator
class ConcreteMediator : public Mediator {
    class Colleague* colleague1;
    class Colleague* colleague2;
public:
    void setColleague1(Colleague* c1) { colleague1 = c1; }
    void setColleague2(Colleague* c2) { colleague2 = c2; }
    void send(const std::string& message, Colleague* colleague) override {
        if (colleague == colleague1) {
            colleague2->notify(message);
        } else {
            colleague1->notify(message);
        }
    }
};
// Step 3: Colleague classes
class Colleague {
protected:
    Mediator* mediator;
public:
    Colleague(Mediator* m) : mediator(m) {}
    virtual void send(const std::string& message) = 0;
    virtual void notify(const std::string& message) = 0;
};
class ConcreteColleague1 : public Colleague {
public:
    ConcreteColleague1(Mediator* m) : Colleague(m) {}
    void send(const std::string& message) override {
        mediator->send(message, this);
    }
    void notify(const std::string& message) override {
        std::cout << "Colleague1 gets message: " << message << std::endl;
    }
};
class ConcreteColleague2 : public Colleague {
public:
    ConcreteColleague2(Mediator* m) : Colleague(m) {}
    void send(const std::string& message) override {
        mediator->send(message, this);
    }
    void notify(const std::string& message) override {
        std::cout << "Colleague2 gets message: " << message << std::endl;
    }
};
// Example Usage
int main() {
    ConcreteMediator mediator;
    ConcreteColleague1 colleague1(&mediator);
    ConcreteColleague2 colleague2(&mediator);
    mediator.setColleague1(&colleague1);
    mediator.setColleague2(&colleague2);
    colleague1.send("How are you?");
    colleague2.send("I'm fine, thanks!");
    return 0;
}

Output:

Colleague2 gets message: How are you?
Colleague1 gets message: I'm fine, thanks!

Explanation:

1. Mediator is the abstract interface for communication.

2. ConcreteMediator knows about each colleague and implements cooperative behavior.

3. Colleague classes only communicate with the mediator object instead of communicating directly with each other.

In the example, ConcreteColleague1 sends a message, which is relayed through the ConcreteMediator to ConcreteColleague2, and vice-versa.

7. When to use?

Use the Mediator pattern when:

1. A set of objects communicate in well-defined but complex ways, and you want to avoid tight coupling.

2. Reusing an object is difficult because it communicates with many other objects.

3. You want to centralize external communications to simplify future shifts and changes.


Comments