Overview
The Mediator Design Pattern is used to reduce coupling between components (e.g., classes or modules) by introducing a mediator object that handles communication between them. This pattern promotes loose coupling and centralizes complex communication logic.
Key Characteristics
- Defines an object that encapsulates how a set of objects interact.
- Promotes loose coupling by preventing direct communication between objects.
- Centralizes communication logic within the mediator.
Implementation
The following is an example of a Mediator implementation in Java:
// Mediator interface
interface ChatMediator {
void sendMessage(String message, User user);
void addUser(User user);
}
// Concrete Mediator
class ChatRoom implements ChatMediator {
private List users = new ArrayList<>();
@Override
public void sendMessage(String message, User user) {
for (User u : users) {
if (u != user) {
u.receive(message);
}
}
}
@Override
public void addUser(User user) {
users.add(user);
}
}
// Colleague
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void send(String message);
public abstract void receive(String message);
}
// Concrete Colleague
class ConcreteUser extends User {
public ConcreteUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void send(String message) {
System.out.println(name + " sends: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " receives: " + message);
}
}
// Demo
public class MediatorDemo {
public static void main(String[] args) {
ChatMediator chatMediator = new ChatRoom();
User user1 = new ConcreteUser(chatMediator, "Alice");
User user2 = new ConcreteUser(chatMediator, "Bob");
User user3 = new ConcreteUser(chatMediator, "Charlie");
chatMediator.addUser(user1);
chatMediator.addUser(user2);
chatMediator.addUser(user3);
user1.send("Hello, everyone!");
user2.send("Hi, Alice!");
}
}
When to Use
- When a set of objects communicate in complex but well-defined ways.
- When you want to centralize communication logic to improve maintainability.
- When you want to reduce dependencies between communicating objects.
Advantages
- Reduces coupling between communicating objects.
- Centralizes communication logic, making it easier to manage and maintain.
- Improves scalability by allowing new components to interact through the mediator.
Disadvantages
- Can introduce a single point of failure if the mediator is not implemented carefully.
- May become complex if the number of interactions is very large.