Mediator Design Pattern in Java
1. Introduction
The Mediator Pattern defines an object (the mediator) that centralizes communication between multiple objects, ensuring they don’t directly reference each other.
Instead of classes talking to each other directly, they send messages through the mediator. This reduces dependencies and makes the system more loosely coupled.
2. Real-Life Analogy
Think of a chatroom:
- Users don’t send messages directly to each other.
- Instead, they send messages to the chatroom (Mediator).
- The chatroom is responsible for delivering the message to the intended recipient(s).
3. Structure
- Mediator (Interface) → Declares methods for communication.
- ConcreteMediator → Implements communication logic between colleagues.
- Colleague (Interface/Class) → Defines participants that communicate via the mediator.
- ConcreteColleague → Real participants that send messages through the mediator.
4. Custom Java Example: Chatroom Mediator
Step 1: Mediator Interface
interface ChatMediator {
void sendMessage(String message, User user);
void addUser(User user);
}
Step 2: Concrete Mediator (Chatroom)
import java.util.ArrayList;
import java.util.List;
class ChatRoomMediator implements ChatMediator {
private List users = new ArrayList<>();
@Override
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String message, User sender) {
for (User user : users) {
// Don’t send the message back to the sender
if (user != sender) {
user.receive(message, sender.getName());
}
}
}
}
Step 3: Colleague (User Abstract Class)
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public String getName() {
return name;
}
public abstract void send(String message);
public abstract void receive(String message, String senderName);
}
Step 4: Concrete Users
class ChatUser extends User {
public ChatUser(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, String senderName) {
System.out.println(name + " receives from " + senderName + ": " + message);
}
}
Step 5: Client Code
public class MediatorPatternDemo {
public static void main(String[] args) {
ChatMediator chatRoom = new ChatRoomMediator();
User user1 = new ChatUser(chatRoom, "Alice");
User user2 = new ChatUser(chatRoom, "Bob");
User user3 = new ChatUser(chatRoom, "Charlie");
chatRoom.addUser(user1);
chatRoom.addUser(user2);
chatRoom.addUser(user3);
user1.send("Hello, everyone!");
user2.send("Hi Alice!");
user3.send("Hey folks, what’s up?");
}
}
5. Output
Alice sends: Hello, everyone!
Bob receives from Alice: Hello, everyone!
Charlie receives from Alice: Hello, everyone!
Bob sends: Hi Alice!
Alice receives from Bob: Hi Alice!
Charlie receives from Bob: Hi Alice!
Charlie sends: Hey folks, what’s up?
Alice receives from Charlie: Hey folks, what’s up?
Bob receives from Charlie: Hey folks, what’s up?
6. Benefits
- Loose coupling: Participants don’t need to know each other directly.
- Centralized control: The mediator manages communication.
- Easier to modify: Adding new participants or changing communication logic requires changes only in the mediator.
7. When to Use
- When communication between objects becomes too complex (too many interconnections).
- For systems like chatrooms, air traffic control, or GUIs where many components interact.
Next- Memento Design Pattern in Java