
Introduction
I wanted a useful implementation of the GoF Mediator pattern. It isn't used very much and that
in my opinion is probably due to a lack of a good examples. Here is my concept of Mediator.
Background
Either refer to the Mediator section of the Gang of Four book Design Patterns, or
Wikipedia's article on the subject.
The Solution
How to create a collection of mediated types, managed by a central mediator class.
- Derive your mediated types from
i_mediated
. - Your mediated types ought to implement abstract interfaces.
- Inside your mediated type, declare an interfaces type list. Like so:
typedef cons<Interface1, Interface2, ..., Interface5>::type interfaces;
- Derive your own mediator from
basic_mediator
. - Declare your mediator instance and instances of your mediated types.
Note: they don't have to be internal to the class.
- Call
basic_mediator::bind
on each object that is to be mediated.
and that's it.
Each mediated type can now request an interface reference from your mediator via
the Colleague<I>()
template method.
The Test Code

int _tmain(int , _TCHAR* [])
{
Mediator mediator;
ICfgStateSet& rCfgSet = mediator.getColleague<ICfgStateSet>();
rCfgSet.Configure();
ICfgStateGet const& rCfgGet = mediator.getColleague<ICfgStateGet const>();
ICfgAuthGet const& rAuth = mediator.getColleague<ICfgAuthGet const>();
std::cout << "Cfg::Value = \""
<< rCfgGet.Value() << "\"" << std::endl;
std::cout << "Auth = \"" << rAuth.User()
<< "\":\"" << rAuth.Pass()
<< "\"" << std::endl;
std::cout << "Cfg::Value = \""
<< rAuth.getCfgValueIndirect()
<< "\"" << std::endl;
return 0;
}
A Mediator
and two mediated types (Cfg
and Auth
) are declared which are bound inside
the Mediator
constructor.
Several interfaces to each of these mediated types are also declared.
The main routine exercises the new Mediator
by retrieving several
of the declared interfaces and calling through them.
There is one method getCfgValueIndirect()
which tests the ability of the
Auth
object
to retrieve the ICfgStateGet const
interface using
the Colleague
template method.
Points of Interest
The use of the pointer value of typeid::name
as the interface map key value
was a design choice based upon two things. First, the address is guaranteed to be
idempotent (the same for that type for the life of the program). Second, efficiency,
a single comparison versus strcmp()
, that was a no brainer.
There are some aspects of the interface based design which deserve comment.
- Fine grained interface design appears to be a natural outcome. E.g.,
typedef const<ICfgRead const, ICfgWrite, ICfgFile, ICfgState>::type
.
This appears to be an occurrence of the Facade pattern. - If one wishes to intercept a particular activity within a mediator,
it may be that using a Proxy pattern on the interface would work nicely.
typeid::name
is const sensitive, so take care with your declarations.- The use of static/dynamic cast allows for a robust solution that copes
reasonably well with a variety of inheritance structures.
- The Mediator does not address life time issues.
The example code neatly avoids the problem through aggregation.
There is no reason you can't modify
basic_mediator
to handle smart pointers,
or indeed to have the mediated objects unbind themselves (not yet implemented).
History
First implementation.
Future
The next more complex version I intend to build will address the kinds of
implementations I have found which assumed an event model.
I believe this would be best served by applying an Observer pattern to the mediated types.
This will allow mixing in the notification policy for types that need it, without
forcing this concept on all the mediated types.
Developing various kinds of software using C/C++ since 1984 or so. Started out writing 8086 asm for direct screen i/o and mouse handling etc.
Used several other languages eg. Java, Python, Clipper/dBase, FORTRAN 77, Natural ADABAS, Unix scripting, etc.
Previous role involved Enterprise Content Management on Win32.
Most recently worked on managing secure code example development for an online secure code training product.
securecodewarrior.com