ব্রীজ ডিজাইন প্যাটার্ন


ধরুন একজন প্রোগ্রামার তার নাম যদু মিয়া গ্রাজুয়েশন শেষ করে কোনও একটি সফটওয়্যার ফার্মে প্রোগ্রামার হিসেবে তার ক্যারিয়ার স্টার্ট করলো।
অপারেটিং সিস্টেমের উপর যদু মিয়ার ভালো দক্ষতা ।যে অপারেটিং সিস্টেমের অ্যালগোরিদম গুলো বেশ ভালোভাবে রপ্ত করেছে।
তার বস যদুকে একটি প্রোজেক্টে ইনক্লুড করে দিলো, যে প্রোজেক্টে বেশ কিছু থ্রেড শিডিউলিং অ্যালগোরিদম এ যদুকে কাজ করতে হবে ।
তার বস যদুকে Round Robin অ্যালগোরিদম ইমপ্লিমেন্ট করে নিয়ে আসতে বললো । সে RoundRobin নামে একটি ক্লাস বানিয়ে win32 এপিআই ব্যবহার করে ApplyAlgorithm মেথডের ভেতরে অ্যালগোরিদম ইমপ্লিমেন্ট করে নিয়ে আসলো এভাবেঃ

   public class RoundRobin
   {
       public void ApplyAlgorithm()
       {
           Console.WriteLine("Round Robin algorithm applied here");
       }
   }

এখন যদু তার এই কোড বস কে দেখানোর আগেই বস বললো “শোন যদু ক্লায়েন্ট তার লিনাক্স মেশিনেও এই সফটওয়্যার চালাতে চায়, তুমি লিনাক্স কার্নেল এপিআই ইউজ করে অ্যালগোরিদম লিখে নিয়ে আসো” । যদু যথেষ্ট বুদ্ধিমান ছিলো সে , অবেজক্ট অরিয়েন্টেড কনসেপ্ট ইউজ করতে চাইলো ।
সে প্রথমে তার RoundRobin ক্লাসটি কে একটি ইন্টারফেস বানিয়ে নিলো এভাবেঃ

public interface IRoundRobin
{
    void ApplyAlgorithm();
 }

এরপর সে উইন্ডোজ এর জন্য ক্লাস বানালো এভাবে (যেটা IRoundRobin কে ইমপ্লিমেন্ট করে):

    public class Win32RoundRobin : IRoundRobin
    {
        public void ApplyAlgorithm()
        {
            Console.WriteLine("Round Robin Thread Scheduling using windows 32 API");
        }
    }

একই ভাবে সে লিনাক্সের জন্যে ক্লাস বানালো এভাবে (যেটা IRoundRobin কে ইমপ্লিমেন্ট করে):

    
   public class LinuxRoundRobin : IRoundRobin
    {
        public void ApplyAlgorithm()
        {
            Console.WriteLine("Round Robin Thread Scheduling using Linux Kernel API");
        }
    }

এখন ক্লায়েন্ট কোডে যে এই কোড গুলো ইউজ করলো এভাবেঃ

   public class Program
    {
        public static void Main(string[] args)
        {
            IRoundRobin roundRobin = null;
 
            roundRobin = new Win32RoundRobin();
            roundRobin.ApplyAlgorithm();
 
            roundRobin = new LinuxRoundRobin();
            roundRobin.ApplyAlgorithm();
            
            
            Console.ReadLine();
        }
    }

যদু খুশি মনে গিট এ কোড পুশ দিয়ে রেডি হলো বাসায় ফিরবে । তারপর দিন উইকেন্ড ছিলো সো তার মন এমনিতেই বেশ ফুরফুরে ।
এর মধ্যে যদুর বস তাকে বললো যে , ক্লায়েন্ট শেষ মুহূর্তে তার রিকোয়ারমেন্ট চেঞ্জ করেছে সো তোমাকে আজকে একটু এক্সট্রা আওয়ারস থাকতে হবে ।
যদুর নতুন জব সে বসকে কিছু বলতে পারলো না , সে নিরস মনে বাসায় ফোন দিয়ে জানিয়ে দিলো যে তার বাসায় ফিরতে রাত হবে ।
ক্লায়েন্টের রিকোয়ারমেন্ট হচ্ছে যে , সফটওয়্যারটিকে ম্যাকের জন্যেও সাপোর্ট দিতে হবে এবং Shortest-Job-First (SJF) Scheduling অ্যালগোরিদমও ইমপ্লিমেন্ট করে দিতে হবে।
যদু হাতে এক কাপ গরম কফি নিয়ে বাকি কাজটুকু করতে বসে গেলো । সে তার কোডের ডিজাইনে আরেক লেভেল এর ইনহেরিট্যান্স অ্যাপ্লাই করলো ।
যদু ISchedulingAlgorithm নামে একটি ইন্টারফেস বানালো এবং এর ভেতরে একটি মেথড বানালো ApplyAlgorithm নামে এভাবেঃ

   public interface ISchedulingAlgorithm
    {
        void ApplyAlgorithm();
    }

এখন ক্লায়েন্টের রিকোয়ারমেন্ট হচ্ছে RoundRobin এবং SJF Scheduling Algorithm সেহেতু আমরা দুইটা ইন্টারফেস বানাবো যারা ISchedulingAlgorithm কে ইমপ্লিমেন্ট করবে ।
আমাদের ইন্টারফেস দু’টো হচ্ছে এরকমঃ

public interface IRoundRobin : ISchedulingAlgorithm
{
}

এবং

public interface IShortestJobFirst : ISchedulingAlgorithm
{
 
}

এখন এই দুটি ইন্টারফেসকে ইউজ করে আমরা আমাদের উইন্ডোজ এবং লিনাক্সের Scheduling Algorithm ইমপ্লিমেন্ট করবো । এখানে উইন্ডোজ এবং লিনাক্সের জন্যে RoundRobin Scheduling Algorithm ইমপ্লিমেন্ট করবো এভাবেঃ
উইন্ডোজ এর জন্যেঃ

public class Win32RoundRobin : IRoundRobin
   {
       public void ApplyAlgorithm()
       {
           Console.WriteLine("Round Robin Thread Scheduling using windows 32 API");
       }
   }

লিনাক্সের জন্যেঃ

   public class LinuxRoundRobin : IRoundRobin
    {
        public void ApplyAlgorithm()
        {
            Console.WriteLine("Round Robin Thread Scheduling using Linux Kernel API");
        }
    }

একই ভাবে SJF Algorithm এর ক্ষেত্রে উইন্ডোজ জন্যেঃ

   public class Win32ShortestJobFirst : IShortestJobFirst
   {
       public void ApplyAlgorithm()
       {
           Console.WriteLine("Shortest Job First Thread Scheduling using windows 32 API");
       }
   }

লিনাক্সের জন্যেঃ

   public class LinuxShortestJobFirst : IShortestJobFirst
   {
       public void ApplyAlgorithm()
       {
           Console.WriteLine("Shortest Job First Thread Scheduling using Linux Kernel API");
       }
   }

সবশেষে ক্লায়েন্ট কোডে যদু ইউজ করলো এভাবেঃ

   public class Program
    {
        public static void Main(string[] args)
        {
            IRoundRobin roundRobin = null;
 
            roundRobin = new Win32RoundRobin();
            roundRobin.ApplyAlgorithm();
 
            roundRobin = new LinuxRoundRobin();
            roundRobin.ApplyAlgorithm();
 
            
            IShortestJobFirst shortestJobFirst = null;
 
            shortestJobFirst = new LinuxShortestJobFirst();
            shortestJobFirst.ApplyAlgorithm();
 
            shortestJobFirst = new Win32ShortestJobFirst();
            shortestJobFirst.ApplyAlgorithm();
            Console.ReadLine();
        }
    }

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

Bridge Design Pattern CD
Bridge Design Pattern CD

এখন যদি সে নতুন কোনও অ্যালগোদিম যোগ করতে চায় তাহলে তাকে বর্তমান দুইটি অপারেটিং সিস্টেমের জন্যে মোট ১+১+১=৩ টি ক্লাস এড করতে হবে । তাহলে মোট ক্লাস হবে ৩+৩+৩+১ = ১০ টি । প্রতিবার নতুন অ্যালগোরিদম যোগ করার সময় যদুকে তিনটি করে ক্লাস এড করতে হবে ।
আবার যদি এখানে ম্যাকের জন্যে সাপোর্ট দিতে হয় তাহলে তাকে ১টি করে ক্লাস যোগ করতে হবে । সো যদি অপারেটিং সিস্টেমের সাপোর্ট এবং অ্যালগোরিদমের সংখ্যা বাড়তে থাকে তাহলে যদুকে অনেক অনেক ক্লাস ব্যবহার করতে হবে । এভাবে আস্তে আস্তে সিস্টেমের কমপ্লিক্সিটি বাড়তে থাকবে ।
যদু এই অবস্থায় কোড পুশ করে গভীর রাতে বাসায় চলে গেলো । কিন্তু তার মাথায় কোডের ডিজাইনগুলো ঘুরপাক খেতে লাগলো । সে এই প্রবলেম কিভাবে সল্ভ করবে এই চিন্তায় ভালো করে ঘুমাতে পারলো না । পরদিন একটু দেরী করে অফিসে গিয়ে সে একজন সিনিওর ডেভেলপার এর সাথে বসে তার কোডের প্রবলেম গুলো আলোচনা করতে লাগলো । সিনিওর ডেভেলপার তার প্রবলেম শুনে তাকে একটা শব্দ বললো “ব্রিজ ডিজাইন প্যাটার্ন” । যদু তার ডেস্কে ফিরে এককাপ কফি হাতে নিয়ে নেটে সার্চ দিলো “ব্রিজ ডিজাইন প্যাটার্ন” দিয়ে । কিছুক্ষণ স্টাডি করার পর সে এটা বুঝতে পারলো যে তাকে তার কোডের মইয়ের মত ইনহেরিট্যান্স ব্রেক করতে হবে এবং একটা “ব্রীজ” এর ব্যবস্থা করতে হবে যাতে করে কোডের “অ্যালগোরিদম” এবং “অপারেটিং সিস্টেম” ডিকাপল্ড হয় ।
এইভেবে সে একটি ইন্টারফেস নিলো IScheduling নামে এবং এর ভেতরে ApplyAlgorithm() নামে একটি মেথড নিলো এভাবেঃ

  public interface ISchedulingAlgorithm
   {
       void ApplyAlgorithm();
   }

এবং যে কোনও অ্যালগোরিদম অ্যাপ্লাই করার জন্যে সে একটি ব্রিজ বানালো যাতে করে যে কোনও অপারেটিং সিস্টেম যে কোনও অ্যালগোরিদম

public abstract class AbstractOsBridge
    {
        protected ISchedulingAlgorithm SchedulingAlgorithm;
 
        protected AbstractOsBridge(ISchedulingAlgorithm schedulingAlgorithm)
        {
            SchedulingAlgorithm = schedulingAlgorithm;
        }
        public abstract void ExecuteAlgorithm();
    }

এখন যদু লিনাক্স কার্নেল এর জন্যে অ্যালগোরিদম একজিকিউট করলো এভাবেঃ

public class LinuxKernelApi : AbstractOsBridge
    {
        public LinuxKernelApi(ISchedulingAlgorithm schedulingAlgorithm)
            : base(schedulingAlgorithm)
        {
        }
        public override void ExecuteAlgorithm()
        {
            
            SchedulingAlgorithm.ApplyAlgorithm();
            Console.WriteLine("in Linux kernel...");
        }
    }

এবং উইন্ডোজ এর জন্যে অ্যালগোরিদম একজিকিউট করলো এভাবেঃ

public class Windows32Api : AbstractOsBridge
    {
        public Windows32Api(ISchedulingAlgorithm schedulingAlgorithm)
            : base(schedulingAlgorithm)
        {
        }
 
        public override void ExecuteAlgorithm()
        {
            SchedulingAlgorithm.ApplyAlgorithm();
            Console.WriteLine("in Windows 32 Api...");
        }
    }

সবশেষে যদু তার ক্লায়েন্ট কোডে একে ইউজ করলো এভাবেঃ

public class Program
    {
        public static void Main(string[] args)
        {
            AbstractOsBridge abstractOsBridge = null;
            abstractOsBridge = new LinuxKernelApi(new RoundRobinAlgorithm());
            abstractOsBridge.ExecuteAlgorithm();

            abstractOsBridge = new Windows32Api(new ShortestJobFirst());
            abstractOsBridge.ExecuteAlgorithm();

            Console.ReadLine();
        }
    }

এখন যদু অনায়াসেই যে কোনও অ্যালগোরিদম যে কোনও অপারেটিং সিস্টেমের জন্যে ইমপ্লিমেন্ট করতে পারবে কোনও রকম অবজেক্ট অরিয়েন্টেড প্রিন্সিপাল এর ভায়োলেশন ছাড়াই এবং অনেক অনেক ক্লাস বানানো ছাড়াই ।
যেমন যদুর বস যদি যদুকে নতুন অ্যালগোরিদম যোগ করতে বলে সে একটি ক্লাস বানাবে যে ক্লাসটা ISchedulingAlgorithm

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

এই ছিলো আমাদের ব্রীজ ডিজাইন প্যাটার্ন।
হ্যাপি কোডিং 😀

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