Object Oriented Programming Patterns for Geeks

The Mediator Pattern

 

namespace ooppatterns
{
    using System;
    using System.Collections.Generic;

    internal class Program
    {
        private static void Main(string[] args)
        {
            // Create messenger 
            Messager messenger = new Messager();

            MessageSink AppA_Client1 = new ApplicationA("Client A 1");
            MessageSink AppA_Client2 = new ApplicationA("Client A 2");
            MessageSink AppA_Client3 = new ApplicationA("Client A 3");

            // Application A registers clients...
            messenger.Register(AppA_Client1);
            messenger.Register(AppA_Client2);
            messenger.Register(AppA_Client3);


            MessageSink AppB_Client1 = new ApplicationB("Client B 1");
            MessageSink AppB_Client2 = new ApplicationB("Client B 2");

            // Application B registers clients...
            messenger.Register(AppB_Client1);
            messenger.Register(AppB_Client2);


            MessageSink AppC_Client1 = new ApplicationC("Client C 1");

            // Application C registers clients...
            messenger.Register(AppC_Client1);


            // Direct access to the mediator:
            messenger.Send(AppA_Client1, AppC_Client1, "Hello");
            messenger.Send(AppC_Client1, AppB_Client2, "Hello");

            // Example of clients sending messages...
            AppB_Client2.Send("Client A 3", "Hello");
            AppA_Client3.Send("Client B 1", "Hello");


            // However they can also send to themselves, so
            // you should try to prevent this...
            AppC_Client1.Send("Client C 1", "Hello");
            messenger.Send(AppC_Client1, AppC_Client1, "Hello");

            Console.ReadLine();
        }
    }

    interface IMediator
    {
        void Register(MessageSink messageSink);

        void Send(string from, string to, string message);
    }

    // This could represent a server process accessible by remoting.
    class Messager : IMediator
    {
        private Dictionary<string, MessageSink> _participants = new Dictionary<string, MessageSink>();

        public void Register(MessageSink messageSink)
        {
            if( !this._participants.ContainsKey(messageSink.Name) )
                this._participants.Add(messageSink.Name, messageSink);

            messageSink.Messager = this;
        }

        public void Send(MessageSink from, MessageSink to, string message)
        {
            this.Send(from.Name, to.Name, message);
        }

        public void Send(string from, string to, string message)
        {
            if( this._participants.ContainsKey(to) )
                this._participants[to].Receive(from, message);
        }
    }

    // All messages are sent and recieved through here
    class MessageSink
    {
        private Messager _messager;
        private string _name;

        // Constructor 
        public MessageSink(string name)
        {
            this._name = name;
        }

        // Properties 
        public string Name
        {
            get { return this._name; }
        }

        public Messager Messager
        {
            set { this._messager = value; }
            get { return this._messager; }
        }

        public void Send(string to, string message)
        {
            this._messager.Send(this._name, to, message);
        }

        public virtual void Receive(string from, string message)
        {
            Console.WriteLine("{0} to {1}: '{2}'", from, _name, message);
        }
    }

    // Client applications that wish to communicate with each other
    class ApplicationA : MessageSink
    {
        // Constructor 
        public ApplicationA(string name)
            : base(name) {}

        public override void Receive(string from, string message)
        {
            Console.Write("To ApplicationA: ");
            base.Receive(from, message);
        }
    }

    class ApplicationB : MessageSink
    {
        // Constructor 
        public ApplicationB(string name)
            : base(name) {}

        public override void Receive(string from, string message)
        {
            Console.Write("To ApplicationB: ");
            base.Receive(from, message);
        }
    }

    class ApplicationC : MessageSink
    {
        // Constructor 
        public ApplicationC(string name)
            : base(name) {}

        public override void Receive(string from, string message)
        {
            Console.Write("To ApplicationC: ");
            base.Receive(from, message);
        }
    }
}