মিডিয়েটর ডিজাইন প্যাটার্ন


অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং এ টাইটলি কাপলড নামে একটা বিষয় আছে ।বিষয়টা এমন যে যখন দুটো/এর বেশী অব্জেক্ট/মডিউল একে অপরের সাথে সরাসরি ডেটা আদান প্রদান করে , অথবা কোনও একটি অবজেক্ট এর সামান্য কিছু চেঞ্জ হলে সাথে সাথে অন্যান্য অবজেক্ট এরও কিছু ডেটা/একশন চেঞ্জ হয়ে যায়। টাইটলি কাপলড সিস্টেমে এক বা একাধিক অব্জেকট অন্যান্য অবজেক্ট এর সাথে তৃতীয় কোনও মাধ্যম ছাড়াই সরাসরি যোগাযোগ / ডেটা আদান প্রদান করে থাকে । বড় বড় এন্টারপ্রাইজ অ্যাপ্লিকেশনের কথাই ধরুন যেখানে শত শত অবজেক্ট নিয়ে কাজ হয় সেখানে যদি এই অবজেক্ট গুলো একে অপরের সাথে এরকম টাইটলি কাপলড অবস্থায় থাকে তাহলে এই অ্যাপ্লিকেশন ডেভেলপ করা , মেইনটেইন করা , খুব সহজেই ফাংশনালিটি চেঞ্জ করা যে কোনও ডেভেলপারের দুঃস্বপ্নের কারণ হিসেবে দেখা দিবে। নিচের ছবিটি দেখে ধারণা নিতে পারেন কি অবস্থা হতে পারেঃ
mediator-design-pattern

ফুডু ক্রেডিটঃ সি শার্প কর্নার
মিডিয়েটর ডিজাইন প্যাটার্ন দিয়ে আমরা আমাদের এই সমস্যার সমাধান করে ফেলতে পারি। তাহলে চলুন শিখে ফেলি আমরা মিডিয়েটর ডীজাইন প্যাটার্ন । শুরু করার আগে কোডের মাধ্যমে আমরা শিখে নিব যে, মিডিয়েটর ডীজাইন প্যাটার্ন না ইউজ করলে আমরা কি কি সমস্যার সম্মুখীন হতে পারি ।

মিডিয়েটর ডিজাইন প্যাটার্ন ব্যবহারের আগেঃ

ধরুন আমরা একটি মেসেঞ্জার বানাতে চাই, যেখানে অনেকগুলো ইউজার থাকবে । ইউজার  অন্যান্য ইউজার কে মেসেজ পাঠাতে পারবে অথবা কোনও ফাইল এটাচমেন্ট হিসেবে পাঠাতে পারবে।

ইউজার এর জন্য আমাদের একটি ক্লাস লাগবে । এখন আসুন দেখে নিই এই ইউজার ক্লাসে কি কি থাকবেঃ

  • ইউজারের নাম ।
  • ইউজারের ম্যাসেজ ।
  • যাদের পাঠাবে তাদের একটি লিস্ট, অর্থাৎ ইউজারের লিস্ট ।
  • ম্যাসেজ সেন্ড করার জন্য একটি মেথড , যেখানে আর্গুমেন্ট হিসেবে একটি ইউজারের অবজেক্ট থাকবে (কেননা একজন ইউজার অন্য ইউজার কে ম্যাসেজ পাঠাবে)
  • ইউজার চেক করার জন্য একটি মেথড (চেক করা লাগবে কেননা একজন ইউজার একজন ইউজারকে ম্যাসেজও পাঠাতে পারে আবার হয়তো অন্য কোনও ইউজারকে একটা এটাচমেন্ট হিসেবে একটা ফাইলও পাঠাতে পারে)

তাহলে আমাদের ইউজার ক্লাসটা এরকম হবেঃ


public abstract class User
{
       protected string Name { get; set; }
       public string Message { get; set; }
       protected readonly List<User> PersonList = new List<User>();
       protected User(string name)
       {
           Name = name;
       }

       public void SendMessage(User user)
       {
           if (user != null)
           {
               PersonList.Add(user);
           }

           UserChecking();
       }
       protected abstract void UserChecking();
   }

ক্লাস এবস্ট্রাক্ট রাখা হয়েছে কেননা আলাদা আলাদা ইউজারকে আলাদা আলাদা ম্যাসেজ / ফাইল পাঠানো হতে পারে ।

এখন আমরা দুইটা ইউজার বানাবো যারা এই ইউজার ক্লাসকে এক্সটেন্ড করবে।

প্রথম ইউজারঃ

     public class UserOne : User
     {
        public UserOne(string name)
            : base(name)
        {
        }

        protected override void UserChecking()
        {
            foreach (User person in PersonList)
            {
                if (person.GetType() == typeof(UserTwo))//User will send message to UserTwo Only
                {
                    Console.WriteLine("From " + Name + ":" + Message);
                }

            }
        }
    }

এখানে লুপের ভেতর চেক করা হয়েছে যে প্রথম ইউজার শুধু মাত্র অন্য ইউজারের কাছে ম্যাসেজ পাঠাতে পারবে ( আমাদের ক্ষেত্রে ইউজার টু)।

একই ভাবে দ্বিতীয় ইউজারঃ

    public class UserTwo : User
    {
        public UserTwo(string name)
            : base(name)
        {
        }

        protected override void UserChecking()
        {
            foreach (User person in PersonList)
            {
                if (person.GetType() == typeof(UserOne))
                {
                    Console.WriteLine("From " + Name + ":" + Message);
                }
            }
        }
    }

দ্বিতীয় ইউজারের ক্ষেত্রে চেক করা হয়েছে যে এটি শুধু প্রথম ইউজারের কাছে মেসেজ পাঠাতে পারবে ।
এখন এই কোড আমাদের ক্লায়েন্ট কোডে ইউজ করতে পারি এভাবেঃ

    public class Program
    {
        public static void Main(string[] args)
        {
            var personOne = new UserOne("Moin")
            {
                Message = "Hi Sujon,  How are you?"
            };

            var personTwo = new UserTwo("Sujon")
            {
                Message = "I am fine, but where is my money?"
            };
            personOne.SendMessage(personTwo);
            personTwo.SendMessage(personOne);
            Console.ReadLine();
        }
    }

আমরা যে চ্যাট সিস্টেম ডেভেলপ করলাম এর সমস্যাগুলো আসুন চিহ্নিত করিঃ

  1. প্রত্যেক ইউজার প্রত্যেক ইউজারের সাথে সরাসরি যোগাযোগ করছে ।
  2. এই চ্যাট অ্যাপ্লিকেশন ১০০ জন ইউজ করলে আমাদের ১০০ বার If else কন্ডিশন লাগাতে হবে যেটা  OOP এর open closed principle রুল এর ভায়োলেশন । কেননা নতুন ইউজার আসলে আমাদের নতুন কন্ডিশন যোগ করতে হবে ।
  3. ১০০ জন ইউজার এই সিস্টেম ইউজ করলে সবার কাছে ১০০*৯৯ টি If Else কন্ডিশন থাকবে !!!!!! চিন্তা করা যায় ।
  4. এই অবজেক্ট গুলোর কোনও একটিতে সামান্য একটু চেঞ্জ হলে , বাকি সবগুলো অবজেক্ট গুলোকে নোটিফাই করতে হবে , যেটা ব্যাপক পিড়াদায়ক কাজ ।

মিডিয়েটর ডিজাইন প্যাটার্ন ইউজ করার পরঃ

মিডিয়েটর ডিজাইন প্যাটার্ন আমাদের অবজেক্টদের মধ্যে যোগাযোগের মাধ্যম হিসেবে কাজ করে । অর্থাৎ এই প্যাটার্ন আমাদের অবজেক্টদের মুরুব্বী হিসেবে কাজ করে এবং খেয়াল রাখে যাতে করে এরা নিজেদের মধ্যে সরাসরি যোগাযোগ করতে না পারে । কোনোও অবজেক্ট অন্য অবজেক্ট এর সাথে যোগাযোগ করতে হলে অবশ্যই এই মুরুব্বীর মাধ্যমে করতে হবে । একটি অবজেক্ট এই মুরুব্বীকে বলবে যে আমার অন্য একটি অবজেক্ট এর কাছে কিছু বার্তা পাঠানো দরকার , মুরুব্বী সেই বার্তা নিয়ে কাংখিত অবজেক্ট এর কাছে বার্তা পাঠিয়ে দিবে ।

তাহলে আমাদের মুরুব্বীর প্রধান কাজ হচ্ছে ইউজারের কাছ থেকে ম্যাসেজ নেয়া এবং কাংখিত ইউজারকে ম্যাসেজ সেন্ড করা ।
সো এই দুইটি কাজের জন্য আমরা একটা ইন্টারফেস বানাতে পারি এভাবেঃ

    public interface IChatMediator
    {
        void SendMessage(string message, User user);
        void AddPerson(User user);
     }

এখন এই মুরুব্বীকে আমাদের কোড এ ইউজ করতে গেলে আমাদের ইউজার ক্লাসে একটু চেঞ্জ করতে হবে এভাবেঃ

  public abstract class User
   {

       protected IChatMediator ChatMediator;
       protected string Name { get; set; }

       protected User(string name, IChatMediator chatMediator)
       {
           Name = name;
           ChatMediator = chatMediator;
       }

       public abstract void Send(string message);
       public abstract void Receive(string message);
   }

এবং আমাদের মুরুব্বী মিডিয়েটর ইন্টারফেসের ইমপ্লিমেন্টেশন হবে এভাবেঃ

   public class ChatMediator : IChatMediator
    {
        private readonly List<User> _personList;

        public ChatMediator()
        {
            _personList = new List<User>();
        }
        public void SendMessage(string message, User user)
        {

            foreach (User u in _personList)
            {
                //message should not be received by the user sending it
                if (u != user)
                {
                    u.Receive(message);
                }
            }
        }

        public void AddPerson(User user)
        {
            _personList.Add(user);

        }
    }

এখন ইউজার ক্লাসের ইমপ্লিমেন্টেশন হবে এরকমঃ

    public class UserOne : User
    {
        public UserOne(string name, IChatMediator chatMediator)
            : base(name, chatMediator)
        {
        }

        public override void Send(string message)
        {
            Console.WriteLine(Name + " :Sending Message=" + message);
            ChatMediator.SendMessage(message, this);
        }

        public override void Receive(string message)
        {
            Console.WriteLine(Name + " :Received Message:" + message);
        }
    }

ব্যস আমাদের মুরুব্বী রেডি , এখন আমরা অনেকগুলো ইউজার বানাবো আর তাদের কে হ্যালো বলবো এভাবেঃ

   public class Program
    {
        public static void Main(string[] args)
        {
            IChatMediator chatMediator = new ChatMediator();
            User me = new UserOne("Forhad", chatMediator);
            User person1 = new UserOne("Shuvo", chatMediator);
            User person2 = new UserOne("Sujon", chatMediator);
            User person3 = new UserOne("Moin", chatMediator);
            chatMediator.AddPerson(person1);
            chatMediator.AddPerson(person2);
            chatMediator.AddPerson(person3);

            me.Send("Hi All, How are you?");

            Console.ReadLine();
        }
    }

লক্ষ্য করে দেখুন , এখানে কোনও অবজেক্ট সরাসরি ইউজার অবজেক্ট এর কাছে ম্যাসেজ পাঠাচ্ছে না , পাঠাচ্ছে আমাদের মুরুব্বীর কাছে ।
এভাবে আমরা মিডিয়েটর ডিজাইন প্যাটার্ন দিয়ে অনেক স্ক্যালাবল এবং লুজলি কাপলড সিস্টেম বানাতে পারি ।

হ্যাপি কোডিং 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s