The Mediator Design Pattern diminishes the intricacy of communication between entities by incorporating an intermediary entity. It disentangles the direct interplay between entities by providing an intermediary that facilitates their communication. Rather than entities engaging in direct communication, they transmit messages to the intermediary, which then forwards these messages to the respective entities.
When an entity desires to communicate with another entity or entities, it abstains from direct interaction. Instead, it dispatches its message to the intermediary mediator entity, whose role is to direct these messages to the intended entity or entities.
This pattern is particularly useful in scenarios where a group of objects interact in complex ways and need to be decoupled for better maintainability and extensibility. In this guide, we will delve into the Coordinator Design Scheme using Java. We'll explore its configuration, execution, and application. Moreover, we'll scrutinize recommended practices for executing the scheme and emphasize its benefits.
Real life Example
- In Air traffic controller. All incoming or outgoing flights don't communicate with each other directly, Instead they communicate with airport's air traffic controller.
- Group chat room. One member of group sends message to chat server, then it is chat server's responsibility to propagate this message to all other members of the group.
Structure of the Factory Design Pattern
- Mediator Interface : Interface used by Colleagues to interact with Mediator.
- Concrete Mediator : Implements Mediator Interface and maintains a list of Colleagues communicating with each other. It facilitates the communication between Colleages by routing their messages to destination colleague(s). It is the communication center for the Colleagues.
- Colleague(s) : Object(s) communicating with other object(s). It contains a reference of Mediator object.
Advantages of Mediator Design Pattern
- Decoupling of Colleagues : A primary advantage of the Facilitator Design Approach is the decoupling of Colleagues. Colleagues refrain from direct references to one another, diminishing dependencies and fostering a more segmented design.
- Enhanced Maintainability :The achieved decoupling through the mediator enhances maintainability. Modifications to one colleague don't necessitate alterations to other colleagues or the mediator, enhancing the system's resilience to changes.
- Centralized Communication : The mediator centralizes communication logic. This centralization streamlines the overall system design by providing a singular control point for orchestrating interactions among colleagues.
- Encouragement of Reusability : The mediator can be reused in diverse scenarios. As long as the communication protocol among colleagues remains consistent, the same mediator implementation can be applied in various contexts.
- Simplified Extension : The Mediator Design Approach renders the system more extensible. Introducing new colleague or modifying existing ones is less daunting since changes are confined to the mediator rather than scattered across the system.
- Streamlined Communication : Colleagues communicate through the mediator, simplifying communication pathways. This simplification diminishes the likelihood of communication-related issues and facilitates a clearer understanding and debugging of the system.
- Promotion of Loose Coupling : Loose coupling stands out as a key benefit of the Mediator Design Approach. Colleagues exclusively interact with the mediator, and alterations to one colleague don't cascade to others. This loose coupling elevates the overall stability of the system.
- Centralized Control : The mediator furnishes centralized control over communication flow. This centralized control proves beneficial in scenarios where specific rules or policies need enforcement during communication among colleagues.
- Support for Complex Systems : The Mediator Design approach is particularly beneficial in complex systems featuring intricate interactions among multiple objects. It introduces a structured method for managing these interactions, mitigating the complexity of the overall system.
When we should use Mediator Pattern
- When we want to simplify the communication between lots of object interacting with each other.
- When we want to centrally manage all communication between Colleagues.
Implementation of Mediator Design Pattern
Here, we will implement a chat group using mediator pattern. ChatServer is the Mediator interface class that is used by the char participants to interact with mediator object.
ChatServer.javapublic interface ChatServer { public void addUser(Participant user); public void sendMessage(Participant user, String message); }
ChatServerMediator is the concrete implementation of ChatServer interface. It will act as a mediator object, whose primary responsibility is to route messages between participants.
ChatServerMediator.javaimport java.util.List; import java.util.ArrayList; public class ChatServerMediator implements ChatServer { private List<Participant> participantList; public ChatServerMediator(){ participantList = new ArrayList<Participant>(); } public void addUser(Participant user){ participantList.add(user); } public void sendMessage(Participant user, String message){ for(Participant p : participantList){ if(p != user){ p.receiveMessage(message, user); } } } }
Participants is the member of the chat group, communication with each other by calling mediator(ChatServerMediator).
Participant.javapublic class Participant { private String userName; private ChatServer charServerMediator; public Participant(String name){ this.userName = name; } public String getUserName(){ return userName; } public void joinChatGroup(ChatServer chatGroup){ charServerMediator = chatGroup; charServerMediator.addUser(this); } public void sendMessage(String message){ System.out.println(userName +", Sending this message : \"" + message + "\""); charServerMediator.sendMessage(this, message); } public void receiveMessage(String message, Participant user){ System.out.println(userName + ", Received : \"" + message + "\", From : " + user.userName); } }
MediatorPatternExample will simulate the communication between participants using ChatServerMediator.
MediatorPatternExample.javapublic class MediatorPatternExample { public static void main (String args[]){ ChatServer chatServer = new ChatServerMediator(); Participant jack = new Participant("Jack"); Participant george = new Participant("George"); Participant emilly = new Participant("Emilly"); jack.joinChatGroup(chatServer); george.joinChatGroup(chatServer); emilly.joinChatGroup(chatServer); // Jack is sending message jack.sendMessage("Hi Everyone, I am Jack"); // Emilly replying to Jack emilly.sendMessage("Hi Jack, How are you"); } }
Output
Jack, Sending this message : "Hi Everyone, I am Jack" George, Received : "Hi Everyone, I am Jack", From : Jack Emilly, Received : "Hi Everyone, I am Jack", From : Jack Emilly, Sending this message : "Hi Jack, How are you" Jack, Received : "Hi Jack, How are you", From : Emilly George, Received : "Hi Jack, How are you", From : Emilly
Best Practices of Mediator Design Pattern
- Formulate the mediator interface with a precise and succinct set of methods for communication among collaborators. Avoid introducing unnecessary methods that might contribute to an excessively large interface.
- Ensure that collaborators remain oblivious to each other's presence. Their communication should exclusively occur through the mediator, and modifications to one collaborator should not affect others. This autonomy simplifies maintenance and extensibility.
- Encapsulate the communication logic between collaborators within the mediator. Collaborators must not possess direct references to each other, fostering loose coupling and autonomy.
- If the mediator necessitates maintaining state information, manage it judiciously to prevent it from evolving into a monolithic controller. Contemplate using a distinct state manager or delegating state management to the collaborators when appropriate.
- Define interfaces for collaborators to establish a consistent communication protocol. Concrete collaborators implement these interfaces, and the mediator interfaces with them rather than concrete implementations.
- Fashion the mediator for reusability across various scenarios. Refrain from embedding specific collaborator interactions in the code, allowing the mediator to adapt to diverse contexts.
- Avoid crafting a "Supreme" mediator tasked with overseeing all interactions in the system. Instead, contemplate devising multiple intermediaries with specific responsibilities, fostering a more segmented and sustainable design.
- Establish a uniform approach to error handling within the mediator. Determine whether errors during communication should be centrally managed in the mediator or if individual collaborators should handle errors.
- Employ clear and meaningful names for mediator methods and collaborators. Naming conventions like sendMessage and receiveMessage contribute to lucidity regarding the functions of these methods.
- Document the mediator-related classes and methods meticulously. Explicitly delineate the responsibilities of the mediator, collaborators, and any other pertinent components. Provide examples or documentation elucidating how to extend or modify the mediator for diverse scenarios.
Memento Design Pattern |
Bridge Design Pattern |
Interpreter Design Pattern |
Facade Design Pattern |
Observer Design Pattern |
List of Design Patterns |