Click here to Skip to main content
15,878,945 members
Articles / Programming Languages / C++
Article

Mediator Pattern (basic_mediator template class)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
21 May 2012MIT3 min read 21K   304   11   6
An implementation of the GoF Behavioral Design Pattern - Mediator.

Image 1

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

Image 2

C++
int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
   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.

  1. 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.
  2. 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.
  3. typeid::name is const sensitive, so take care with your declarations.
  4. The use of static/dynamic cast allows for a robust solution that copes reasonably well with a variety of inheritance structures.
  5. 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.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Australia Australia
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

Comments and Discussions

 
QuestionIs this an antipattern? Pin
David 'dex' Schwartz15-Aug-12 14:28
David 'dex' Schwartz15-Aug-12 14:28 
AnswerRe: Is this an antipattern? Pin
David 'dex' Schwartz13-Oct-12 4:13
David 'dex' Schwartz13-Oct-12 4:13 
AnswerRe: Is this an antipattern? Pin
David 'dex' Schwartz26-Jan-17 19:10
David 'dex' Schwartz26-Jan-17 19:10 
GeneralMy vote of 5 Pin
Volynsky Alex21-May-12 6:22
professionalVolynsky Alex21-May-12 6:22 
GeneralRe: My vote of 5 Pin
David 'dex' Schwartz21-May-12 15:05
David 'dex' Schwartz21-May-12 15:05 
AnswerRe: My vote of 5 Pin
Volynsky Alex21-May-12 22:52
professionalVolynsky Alex21-May-12 22:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.