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

Mediator Pattern (basic_mediator template class)

, 21 May 2012 MIT
Rate this:
Please Sign up or sign in to vote.
An implementation of the GoF Behavioral Design Pattern - Mediator.

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

Share

About the Author

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

Comments and Discussions

 
QuestionIs this an antipattern? PinmemberDavid 'dex' Schwartz15-Aug-12 14:28 
AnswerRe: Is this an antipattern? PinmemberDavid 'dex' Schwartz13-Oct-12 4:13 
GeneralMy vote of 5 PinmemberVolynsky Alex21-May-12 6:22 
GeneralRe: My vote of 5 PinmemberDavid 'dex' Schwartz21-May-12 15:05 
AnswerRe: My vote of 5 PinmemberVolynsky Alex21-May-12 22:52 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.141022.1 | Last Updated 21 May 2012
Article Copyright 2012 by David 'dex' Schwartz
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid