Define an object that encapsulates how a set of objects interact. Promotes loose coupling by keeping objects from referring to each other explicitly.
We have talked previously about the Observer pattern and how it allows us to facilitate interaction between an observable and multiple observers while not requiring tight coupling.
However, the observable/observer relationship is typically one-to-many.
We also discussed how we can use a Facade to bring together multiple components to form a single, cohesive interface.
However, a facade can only send requests to the subsystems; it is not bidirectional.
The mediator can be seen as something like a combination of the Observer and Facade patterns which extends them to support many-to-many interactions without tight coupling.
Consider the case where we have a user interface which contains a button and a text field. We could code the text field so that, every time it’s contents are changed, we check to see if it is empty and, if so, gray out the button.
If we click the button, we could code the button so that when it is clicked we clear out the text box.
However, if we do this with each component directly referencing the other, we have introduced tight coupling and made our code less flexible.
Alternatively, we could subscribe observers to the text field and to the button, then create a Mediator which would observe and interact with both.
The Mediator would then contain the logic which grays out the button, clears the text, etc.
The components know nothing of each other, yet interact!
Of course, this example only includes two components, but the same concept can be extended to several components which gives us our decoupled, many-to-many interactions.
We could even think of our blob Game class being implemented as a Mediator. It could observe multiple blobs and based on those observations, tell the blobs how they should behave.