Click here to Skip to main content
Click here to Skip to main content

Mediator Pattern (basic_mediator template class)

By , 21 May 2012
 

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 /*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

About the Author

David 'dex' Schwartz
Team Leader
Australia Australia
Member
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.
My current work involves Enterprise Content Management on Win32.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionIs this an antipattern?memberDavid 'dex' Schwartz15 Aug '12 - 14:28 
AnswerRe: Is this an antipattern?memberDavid 'dex' Schwartz13 Oct '12 - 4:13 
GeneralMy vote of 5memberVolynsky Alex21 May '12 - 6:22 
GeneralRe: My vote of 5memberDavid 'dex' Schwartz21 May '12 - 15:05 
AnswerRe: My vote of 5memberVolynsky Alex21 May '12 - 22:52 

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 21 May 2012
Article Copyright 2012 by David 'dex' Schwartz
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid