Mediator Design Pattern (Tasarım Deseni) – C#

GoF’ye göre, Medaitor tasarım deseninin amacı;

Allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other. Allows for the actions of each object set to vary independently of one another.

Farklı nesne gruplarının birbirleriyle etkileşim ve iletişim kurma şeklini özetleyerek gevşek bağlantıya (loose coupling) izin verir. Her nesne kümesinin eylemlerinin birbirinden bağımsız olarak değişmesine izin verir.

Mediator tasarım modeli, birden çok nesnenin birbiriyle etkileşime girdiği bir kurumsal uygulamada çok faydalıdır. Nesneler birbirleriyle doğrudan etkileşime girerse, sistem bileşenleri birbiriyle sıkı (tightly-coupled) bir şekilde birleştirilir, bu da daha yüksek bakım maliyeti sağlar ve genişletilmesi zor değildir. Mediator modeli, iletişim için nesneler arasında bir arabulucu sağlamaya ve nesneler arasında gevşek bağlantının (lose-coupling) uygulanmasına yardımcı olmaya odaklanır. Gerçek hayattan bir örnekleme yapacak olursak Hava trafik kontrolü istasyonun farklı uçuşlar arasında ki iletişimi sağlama görevi tam bir Mediator modelidir.

Mediator, nesneler arasında bir yönlendirici olarak çalışır ve iletişim yolu sağlamak için kendi mantığına sahip olabilir. Birbirleriyle iletişim kuran sistem nesnelerine Colleagues denir. Genellikle iletişim için abstract class veya interfacez ve ardından implement uygulanan somut class’lara sahibiz. Örneğimizde, kullanıcıların grup sohbeti yapabileceği bir sohbet uygulaması gerçekleştirmeye çalışacağız. Herhangi bir kullanıcı tarafından gönderilen mesaj, gruptaki diğer tüm kullanıcılar tarafından alınmalıdır.

UML Class Diyagramı

Mediator UML Diyagram

Kullanım Sıklığı: orta-düşük

Mediator Prensipleri

  • Mediator: Colleague nesneleri ile iletişim kurmak için bir arabirim tanımlar.
  • ConcreteMediator: Colleague nesnelerini koordine ederek işbirlikçi davranış uygular.
  • Colleague Classes: her Colleague, başka bir Colleague ne zaman iletişim kuracaksa, mediator ile iletişim kurar.

C# Mediator Design Pattern Uygulama

Bu senaryomuzda kullanıcıların grup sohbeti yapabileceği bir sohbet uygulamasını uygulamaya çalışacağız. Her kullanıcı adıyla tanımlanacak ve mesaj gönderip alabilecek. Herhangi bir kullanıcı tarafından gönderilen mesaj, kendisi hariç gruptaki diğer tüm kullanıcılar tarafından alınmalıdır.

Öncelikle somut arabulucular için sözleşmeyi tanımlayacak olan Mediator interface’ini oluşturacağız.

    public interface IChatMediator
    {
        public void sendMessage(string msg, User user);
        void addUser(User user);
    }

Kullanıcılar mesaj gönderip alabilir, böylece Kullanıcı arayüzüne veya soyut sınıfa sahip olabiliriz. Aşağıdaki gibi soyut sınıf olarak Kullanıcı oluşturuyorum.

    public abstract class User
    {
        protected IChatMediator mediator;
        protected string name;

        public User(IChatMediator med, string name)
        {
            this.mediator = med;
            this.name = name;
        }

        public abstract void send(String msg);
        public abstract void receive(String msg);
    }

Kullanıcının mediator nesneye bir referansı olduğuna dikkat edin, bu farklı kullanıcılar arasındaki iletişim için gereklidir.

    public class ChatMediatorImpl : IChatMediator
    {
        private List<User> users;
        public ChatMediatorImpl()
        {
            this.users = new List<User>();
        }
        public void addUser(User user)
        {
            this.users.Add(user);
        }

        public void sendMessage(string msg, User user)
        {
            foreach (User u in this.users)
            {
                //Mesaj gönderen kullanıcı tarafından alınmamalı
                if (u != user)
                {
                    u.receive(msg);
                }
            }
        }
    }

Artık client sistem tarafından kullanılacak somut Kullanıcı sınıfları oluşturabiliriz.

    public class UserImpl : User
    {
        public UserImpl(IChatMediator med, string name):base(med, name)
        {
            
        }
        public override void send(string msg)
        {
            Console.WriteLine(this.name+": Sending Message: "+msg);
            mediator.sendMessage(msg, this);
        }

        public override void receive(string msg)
        {
            Console.WriteLine(this.name+": Received Message: "+msg);
        }
    }

Send() metodunun, mesajı kullanıcılara göndermek için aracı kullandığına ve mediator tarafından nasıl ele alınacağına dair hiçbir fikri olmadığına dikkat edin.

Program.cs – Main Method

IChatMediator mediator = new ChatMediatorImpl();
User user1 = new UserImpl(mediator, "Fatih");
User user2 = new UserImpl(mediator, "Beyazıt");
User user3 = new UserImpl(mediator, "Cem");
User user4 = new UserImpl(mediator, "Zeynep");

mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
mediator.addUser(user4);

user1.send("Merhaba C#");

Sonuç

Fatih: Sending Message: Merhaba C#
Beyazıt: Received Message: Merhaba C#
Cem: Received Message: Merhaba C#
Zeynep: Received Message: Merhaba C#