One of the areas to improve in the software development profession is how we name things. I wanted to mention that because this post is about applying the Mediator design Pattern correctly but I do not really feel comfortable saying “Mediator” because it sounds like a law-based profession instead (see: solicitor), I mean it’d had been ok for me to call it after the guy who invented (similar to how astronomers name comets since 1531) but not definitely like «Programmer», «Requester» or other mumbo jumbo term.
There are three roles in the Mediator design pattern: the Mediator itself, the Concrete Mediator and the Concrete Colleague. In few words, the Concrete Colleague contains an instance of an abstract Mediator, which is mapped to the runtime type during execution. It sounds great but how this can help us?
The mediator is useful when controlling the execution of an algorithm externally, without knowledge of the internal working. In this context externally means that you have two classes and the first class needs to call a function defined the second class. You would normally do it directly similarly to the following example:
class A { public void bar() { B obj = new B(); obj.foo(); } } class B { public void foo() { } }
But what about if you know that foo() is going to change. You could abstract the B class in an interface and invert the dependencies as described in the following code:
class A { public void bar() { Ifoo obj = new B(); obj.foo(); } } class B : Ifoo { public void foo() { } } public interface Ifoo { void foo(); }
But what if you know that A is also going to change? The “Mediator” does the trick by abstracting the first class (role: concrete colleague, A in the example) and inverting the Ifoo (role: concrete mediator) as described in the following code:
class A : IBar { private Ifoo mediator = null; public A(Ifoo med) { mediator = med; } public void bar() { mediator.foo(); } } class B : Ifoo { public void foo() { } } public interface Ifoo { void foo(); } public interface IBar { void bar(); }
In the previous sample both depedencies were inverted, so a consumer would be doing something like:
Ifoo concreteMediator = new B(); IBar concreteColleague = new A(concreteMediator); concreteColleague.bar();
The next question would be: what are god scenarios to apply it? To be honest I have used it only in brownfield projects where a change must be isolated to do it progressively, without affecting the whole system, just like a construction/safety net on a busy street, however I think is useful for any scenario where the client and customer classes change. There is another clever sample here: http://bit.ly/1adXETS
Cheers,
Javier Andrés Cáceres Alvis
Microsoft Most Valuable Professional – MVP