This is the 15th post in a series on design patterns.
Mediator is a behavioral design pattern that lets you reduce chaotic dependencies between objects. The Pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
Imagine you have a form for creating and editing customer profiles. This form consists of various form controls such as checkboxes, buttons, and text fields. The form elements may interact with each other. The submit button, for instance, must validate the values of all fields before submitting data.
By implementing this logic directly in the form element classes, it becomes much harder to reuse these classes in other forms.
Mediator Design Pattern
According to the Mediator pattern, you should halt all direct communication between the components you wish to separate. These components must work indirectly, by calling a special mediator object that redirects calls to the appropriate components. Therefore, the components are only dependent on a single mediator class instead of being coupled to dozens of other classes.
UML Class Diagram
Not familiar with UML Class Diagram? I have written a detailed post on the UML Class diagram.
- Identify a group of tightly coupled classes that would benefit from greater independence.
- Specify the mediator interface and the communication protocol between mediators and various components. In most cases, a single method is sufficient for receiving notifications from components. You need to implement this interface if you want to reuse component classes across different contexts. If the component works with its mediator via its generic interface, you can link the component to a different implementation of the mediator.
- Create the concrete mediator class. The class would benefit from storing references to all the components it manages.
- Components should store references to the mediator object. A mediator object is passed as an argument to the component’s constructor, which establishes the connection.
- Components should call the mediator’s notification method instead of methods on other components. Extract the code that calls other components into the mediator class.
Source Code Implementation
Business logic is contained in various classes called components. Each component has a reference to a mediator, which is declared with the interface type of the mediator. Since the component isn’t aware of the actual class of the mediator, you can reuse it in other programs by linking it to a different mediator.
The Button component class extends the Component.
The Textbox component class extends the Component.
Mediator interfaces define methods of communication with components, including the notification method. This method allows components to pass any context as an argument, including their own objects, but only in such a way that there is no coupling between the receiving component and the sender’s class.
In the ProfileForm class, Concrete Mediators encapsulate relations between various components. Concrete mediators keep references to all the components they manage, and sometimes even manage their lifecycles.
Components must not be aware of each other. When something important occurs within or to a component, it must only notify the mediator. If the mediator receives a notification, it can easily identify the sender, which might be just enough to determine which component should be triggered.
From the component’s perspective, it’s all a black box. The sender doesn’t know who will end up handling the request, and the receiver doesn’t know who sent it in the first place.
// Output Validating First Validating Last Validating firstname.lastname@example.org
When To Apply Mediator Design Pattern
- Use the Mediator pattern when it is hard to change some of the classes due to their tight coupling to other classes.
- You can use this pattern when you cannot reuse a component in another program because it is too dependent on other components.
- The Mediator is useful when you find yourself creating tons of component subclasses just so you can reuse some basic behavior.
Pros of Mediator Design Pattern
- The communications between components can be consolidated into a single location, making it easier to understand and maintain.
- You can introduce new mediators without changing the actual components.
- This reduces the coupling between various components of a program.
- You can reuse individual components more easily.