2007 |
Section 5, Chapter 3 |
Mediator Pattern
Concept
The Mediator pattern allows groups of objects to communicate in a disassociated manner and encapsulates this communication while keeping the objects loosely coupled. The pattern allows objects to communicate on a one-to-one basis and acts as a proxy between objects to facilitate this communication.
Use
If you have a group of objects that need to communicate in some way, but you don't wish to allow them direct access to one another, then using this pattern would be a way to encapsulate this communication in a single object. You find yourself needing to have several objects of similar types communicate in some way with each other. But often this communication can become too entangled and the methods of communication too deeply coupled or too rigid to make changes easily.
Design
The Mediator pattern has two main classes associated with it: the Mediator and the Colleague. The mediator acts as a go-between to the colleagues and controls which two colleagues communicate.
Illustration
interface IMessageEngine
{
void Register(MessageThread thread);
void Send(string from, string to, string message);
}
class MessageEngine : IMessageEngine
{
private Hashtable _messageThreads = new Hashtable();
public void Register(MessageThread thread)
{
if(!_messageThreads.ContainsKey(thread.Name))
_messageThreads.Add(thread.Name,thread);
thread.MessageEngine = this;
}
public void Send(string from, string to, string message)
{
MessageThread thread = (MessageThread)_messageThreads[to];
if(thread != null)
thread.Receive(from, message);
}
}
abstract class MessageThread
{
private IMessageEngine _messageEngine;
.....
public IMessageEngine MessageEngine
{
set{ _messageEngine = value; }
get{ return _messageEngine; }
}
public void Send(string to, string message)
{
_messageEngine.Send(_name, to, message);
}
}
// lack a concrete class implmenting MessageThread here
//Create the message engine which is the mediator
IMessageEngine engine = new MessageEngine();
//instantiate two chat instance message windows
MessageThread imWindow = new IMWindow("Jazzy Jeff");
MessageThread chatWindow = new ChatWindow("Sir Chats-A-Lot");
//Register each chat instance window with the mediator
engine.Register(imWindow);
engine.Register(chatWindow);
//Jazzy Jeff sends a message to Sir Chats-A-Lot
imWindow.Send("Sir Chats-A-Lot","Hey Sir Chats-A-Lot!");
// Sir Chats-A-Lot sends a message back to Jazzy Jeff
chatWindow.Send("Jazzy Jeff","Hey Jazzy!");
Comment: according to the code syntax, it should be C#, however, this sample lacks the implementation of class IMWindow and ChatWindow. |
Comment: this implementation only allow peer-to-peer communication. |
December 2007 |
Section 2, Chapter 9 |
Use
- There is protocol that is observed between the members of a group.
- Messages might also be vetted for content.
- The Mediator pattern makes provisions for more than one mediator.
Colleague | Registers with a Mediator by supplying a Receive method; issues Send requests to other colleagues via the Mediator. |
Mediator | Broadcasts sent messages to all signed-on Colleagues using the Respond delegate. |
class MediatorPattern {
// Mediator Pattern Judith Bishop Sept 2007
/* The Mediator maintains a list of colleagues and specifies the
communication methods that it can mediate - in this case, Send.
Receive is implemented at Colleague level and called via a delegate
supplied by the colleagues to the mediator on sign-on.
*/
class Mediator {
public delegate void Callback(string message, string from);
Callback respond;
public void SignOn(Callback method)
{
respond += method;
}
public void Block(Callback method)
{
respond -= method;
}
public void Unblock(Callback method)
{
respond += method;
}
// Send is implemented as a broadcast
public void Send(string message, string from)
{
respond(message, from);
Console.WriteLine();
}
}
class Colleague {
Mediator mediator;
protected string name;
public Colleague(Mediator mediator, string name)
{
this.mediator = mediator;
mediator.SignOn(Receive);
this.name = name;
}
public virtual void Receive(string message, string from)
{
Console.WriteLine(name +" received from "+from+": " + message);
}
public void Send(string message)
{
Console.WriteLine("Send (From "+name+ "): "+message);
mediator.Send(message, name);
}
}
class ColleagueB : Colleague {
public ColleagueB(Mediator mediator,string name) : base(mediator, name) {}
// Does not get copies of own messages
public override void Receive(string message, string from)
{
if (!String.Equals(from, name))
Console.WriteLine(name +" received from "+from+": " + message);
}
}
static void Main () {
ediator m = new Mediator();
// Two from head office and one from a branch office
Colleague head1 = new Colleague(m,"John");
ColleagueB branch1 = new ColleagueB(m,"David");
Colleague head2 = new Colleague(m,"Lucy");
head1.Send("Meeting on Tuesday, please all ack");
branch1.Send("Ack"); // by design does not get a copy
m.Block(branch1.Receive); // temporarily gets no messages
head1.Send("Still awaiting some Acks");
head2.Send("Ack");
m.Unblock(branch1.Receive); // open again
head1.Send("Thanks all");
}
}
Comment: this implemetation allows broadcasting to all the other colleagues.. |
2016 |
Chapter 18 |
Comment: the stupid thing of this implementation is that it does not generalize the concept Friend, which is usually referred as colleague, it defines a class for each friend entity, that means for each entity that wants to join the party, you need a class for it. |