Programmers encounter same problems over and over again. The common solution to such problems, that is generic and reusable enough to be used millions of times, is called a design pattern. Lets have a closer look at a mediator pattern that is often unfairly left unnoticed.
A design pattern is a general solution to an occurring software engineering problem. Its neither code itself nor can be directly transformed into code. A design pattern is rather a template that describes how to solve a problem.
Mediator lends itself to solving following problems:
- Tight coupling of objects that directly interact with each other.
- Interaction logic is distributed among a set of objects and cannot be reused.
- Interaction logic is hard to test.
- Interaction logic cannot be changed independently.
Mediator object encapsulates the interaction policies in a hidden and unconstraining way. Objects being manipulated by mediator have no idea it exists. It sits quietly behind the scenes and imposes its policies without their permission or knowledge.
Mediator is best demonstrated by a real word example. The code below is taken from the sample project created for this article.
Imagine, you are adding search history feature to an existing search screen. Here are the use cases to be implemented:
- Show a list of latest search terms.
- Add new terms to the list.
- Preserve search terms when an application is closed.
The below diagram shows components structure.
HistoryRepository is an example of Repository design pattern. It abstracts away details of how search history is persisted.
HistoryView is a simple interface that removes coupling between
SearchHistoryMediator has dependencies injected in initializer. It immediately subscribes for
UISearchBar events and sets initial state for
HistoryView. If block-based KVO syntax looks unfamiliar, I recommend checking WWDC session What’s New in Cocoa Touch, 21m.
The rest of interaction logic is performed in
Here are few lines from from
SampleViewController that show how trivial it is to attach the Mediator to an existing search bar.
In the above example, the Mediator handles
UISearchBar events and sets
HistoryRepository states accordingly. The Mediator ensures that components are loosely coupled and they don’t call each other explicitly.
Consider using Mediator every time:
- Interaction between a set of objects is well defined and complex.
- A common point of control over a set of objects is required.
Although Mediator is a well-known pattern, it’s not as widely used as it could. As long as you clearly understand Mediator usage, it will become a significant tool in your toolset.