সিম্পল ফ্যাক্টরি, ফ্যাক্টরি মেথড আর অ্যাবস্ট্রাক্ট ফ্যাক্টরি ডিসাইন প্যাটার্ন
যেকোনো ডিসাইন প্যাটার্ন বোঝার জন্য সেটা কী সমস্যার সমাধান করে সেটা খুব ভালো করে বোঝা জরুরি।
চলুন একটা কাল্পনিক ঘটনা বা গল্পের মাধ্যমে আজকের ডিসাইন প্যাটার্ন গুলোর উপযোগিতা বোঝার চেষ্টা করি।তার আগে বলে নেই: পুরো আইডিয়া আর কোড “Head First Design Patterns” বই থেকে নিয়ে আমি আমার মতো কিছু পরিবর্তন করে নিয়েছি। সুতরাং পুরো ক্রেডিটটাই ওই বইয়ের লেখকদের প্রাপ্য। আর লেখাটা একটু লম্বা, তাই ধৈর্য ধরে, সময় নিয়ে পড়ার অনুরোধ থাকলো।
পুরো সিম্পল ফ্যাক্টরির কোড, টেস্ট ড্রাইভ কোড সহ এই Repl.it লিংকে দিয়ে দিয়েছি। আর পুরো ফ্যাক্টরি মেথড ডিসাইন প্যাটার্নের কোড, টেস্ট ড্রাইভ কোড সহ এই Repl.it লিংকে দিয়ে দিয়েছি, দেখে নিতে পারেন। রেডি?
সিম্পল ফ্যাক্টরি:
ধরুন ঢাকায় পিৎজা হাটের ব্যবসা দেখে আপনার মনে হলো নিজেই একটা পিৎজার দোকান খুলে বসবেন। শুরুতে শুধু “চীজ” আর “ভেজি” পিৎজা দিয়ে শুরু করলেন। ভাবলেন একটা ব্র্যান্ডিং করে ফেলা উচিত। দোকানের নাম দিলেন “পিৎজা ঘর”। ব্যবসা বেশ ভালো চলতে লাগলো। আপনার দোকানের জন্য খুব সহজ আর ছোট একটা কোড লিখে ফেললেন। কাস্টমারের অর্ডার অনুযায়ী হয় ‘চীজ’ অথবা ‘ভেজি’ পিৎজা বানিয়ে রিটার্ন করে দেয়াই এর কাজ। কিছু অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং -এর ধারণা থাকায় বুদ্ধি করে আবার পিৎজার জন্য একটা আলাদা ক্লাস লিখে রাখলেন। যেহেতু সব পিৎজারই মূল উপকরণ মোটামুটি একই, এই যেমন রুটি (Dough), সস (Sauce) আর বিভিন্ন টপিংস (toppings) — তাই একটা পিৎজা সুপার ক্লাস তৈরী করে রাখলেন। পিৎজা প্রসেস করা, বেইক করা, কাটা আর প্যাকেট করা ইত্যাদি কমন ফাঙ্কশন কোড গুলোও এই সুপার ক্লাসে রেখে দিলেন। কিন্তু কেউ যেন ভুল করে এই সুপার পিৎজা ক্লাস থেকে আবার অবজেক্ট তৈরি করে না বসে, সেটা কি করে বন্ধ করা যায়? আপনার মনে পড়লো, কোনো জাভা ক্লাসকে অ্যাবস্ট্রাক্ট (abstract) ডিক্লেয়ার করে দিলে সেটা থেকে আর অবজেক্ট তৈরী করা যায় না। তাই পিৎজা সুপার ক্লাসকে অ্যাবস্ট্রাক্ট করে দিলেন। কোড দেখতে অনেকটা নিচের মতো হলো (ছবি ১):
এবার চলুন চীজ আর ভেজি পিৎজার জন্য এই সুপার ক্লাস থেকে দুটো আলাদা সাবক্লাস তৈরী করা যাক। ধরুন, চীজ আর ভেজি পিৎজার মধ্যে তফাৎ হচ্ছে রুটির পুরুত্বে আর কিছু টপিংসের ভিন্নতায়। তাই দুটো আলাদা সাবক্লাসে, পিৎজা সুপার ক্লাসকে এক্সটেন্ড করে চীজ আর ভেজি পিৎজা ইমপ্লিমেন্ট করে ফেললেন (ছবি ২, ৩):
আর আপনার দোকানের জন্য, অর্থাৎ কাস্টমারের অর্ডার অনুযায়ী চীজ কিংবা ভেজি পিৎজা ডেলিভারি করার জন্য লিখে ফেললেন আরেকটা ক্লাস! সেটার orderPizza(String type) মেথডের ভেতরেই আসলে new কীওয়ার্ড ব্যবহার পিৎজা অবজেক্ট তৈরী হচ্ছে। কোড দেখতে অনেকটা নিচের মতো হলো (ছবি ৪):
কয়েকদিন পর কাস্টমারেরা ‘চীজ’, ‘ভেজি’ পিৎজার পাশাপাশি ‘চিকেন’, ‘বীফ’ ইত্যাদি বিভিন্ন টাইপ পিৎজা চাইতে লাগলো। সুখের সমস্যা! নতুন পিৎজার জন্য আলাদা সাবক্লাস তৈরী না হয় করলেন (সেটা এড়ানোর উপায় নেই), কিন্তু আপনার ছোট দোকানে এতো এতো পিৎজা বানানো তো সম্ভব না। তাছাড়া যতবারই নতুন কোনো পিৎজা চালু করবেন, ততবারই আপনার দোকানের কোডে (ছবি ৪) আরেকটা ‘else if ‘ কন্ডিশন যোগ করতে হবে। এই ব্যাপারটা তো সুবিধার ঠেকছে না, দোকান চালু রেখে (অর্থ্যাৎ কোড পরিবর্তন না করে) কিভাবে এটা করা যায়? এখন উপায় কি?
আপনি ভেবে একটা উপায় বের করলেন। ঠিক করলেন একটা ছোটোখাটো ফ্যাক্টরি খুলে পিৎজা বানানোটা সেখানেই করবেন। আর আপনার দোকানে শুধু অর্ডার নিতে থাকবেন, অর্ডার অনুযায়ী আপনার নিজের ফ্যাক্টরি থেকেই পিৎজা আনবেন। এতে সুবিধা হচ্ছে যে পিৎজা বানানোর কোনো পরিবর্তন হলে, যেমন নতুন কোনো মেশিন কিংবা নতুন নতুন টাইপ পিৎজা অফার করতে চাইলে সব পরিবর্তন আপনার ফ্যাক্টরির মধ্যেই সীমাবদ্ধ থাকবে, আপনার দোকানের কোডে কোনো পরিবর্তন করতে হবে না। যেমন ভাবা, তেমন কাজ! দোকানের কোড থেকে পিৎজা তৈরির কোডটা কেটে নিয়ে লিখে ফেললেন সিম্পল ফ্যাক্টরি ক্লাসের কোড, অনেকটা নিচের মতো:
আর আপনার মূল দোকানে শুধু রেখে দিলেন সেই নতুন ফ্যাক্টরির একটা রেফারেন্স।এতে করে মূল দোকানের কোড (ছবি ৪) পরিবর্তন করে হয়ে গেলো নিচের মতো (ছবি ৬)। এখন নতুন অর্ডার আসলেই এ যেন অনেকটা ফোন করে ফ্যাক্টরিকে পিৎজা তৈরি করতে বলে দেয়া। খেয়াল করে দেখুন, ভবিষ্যতে যতই নতুন পিৎজা যোগ হোক না কেন, দোকানের এই কোডের আর কোনো পরিবর্তন হবে না। ব্যাপারটা মজার না?:
এই যে Separation of concern — আপনার এই ধারণাটাই সিম্পল ফ্যাক্টরি (Simple Factory)। এবার মন খারাপ করা আসল কথাটা বলি: সিম্পল ফ্যাক্টরি কিন্তু আসলে কোনো ডিসাইন প্যাটার্নই না!! Head First Design Pattern বইয়ে একে শুধু ডিসাইন প্যাটার্ন-এর অনারেবল মেনশন দেয়া হয়েছে! কিন্তু সে যাই হোক, আশার কথা হচ্ছে, এই কোড গুলো আমাদের কাজে লাগবে। তাছাড়া আমরা আর কিছু না হলেও অন্তত অবজেক্ট ওরিয়েন্টেড ডিসাইনের একটা ব্যবহার তো শিখলাম!
পুরো কোডটা, টেস্ট ড্রাইভ কোড সহ এই Repl.it লিংকে দেয়া আছে, দেখে নিতে পারেন।
ফ্যাক্টরি মেথড ডিসাইন প্যাটার্ন:
এবার ধরুন ঢাকায় আপনার ব্যবসা দেখে উৎসাহিত হয়ে আপনার এক সিলেটি বন্ধু আপনাকে প্রস্তাব দিলো যে সিলেট শহরে তিনি আপনার “পিৎজা ঘর” -এর একটা ব্রাঞ্চ খুলবেন এবং তিনি নিশ্চিত যে দোকানটি খুব ভালো চলবে। আপনি প্রস্তাবে রাজি হতেই তিনি বলে বসলেন:
“জানিস, সিলেটি কাস্টোমাররা ভেজি পিৎজা তে সাতকরা-র টুকরা দিয়ে দিলে বেশি বেশি খাবে। সাতকরা চিনিস না, ঐ যে সিলেটি এক ধরণের লেবু, স্বাদ একটু তিতা কিন্তু অসম্ভব সুন্দর গন্ধ।পিৎজার রুটিটাও একটু মোটা করে দিতে হবে! আর চীজ পিৎজাতে একটু বেশি চীজ — ব্যস, তাইলেই সিলেটি কাস্টমারেরা খুব খাবে, ব্যবসাই ব্যবসা !”
আপনি ভাবছেন: প্রস্তাব তো খারাপ না, কিন্তু এই যে পিৎজার পরিবর্তন, সেটা কি করে হবে? যদিও দোকানের কোড একই থাকবে, কিন্তু আপনার ফ্যাক্টরির বানানো পিৎজা তো আর সিলেটে চলবে না। বুঝলেন যে আপনার পিৎজার রেসিপি বন্ধুকে দিয়ে দিতে হবে, সাথে তাকে তার নিজের মতো কিছু পরিবর্তন করার সুযোগও দিতে হবে। যেমন, ভেজি পিৎজা তে সাতকরার টুকরা কিংবা চীজ পিৎজাতে আরো বেশি চীজ ইত্যাদি। আপনার বন্ধু নিচের মতো করে সিলেটি ভেজি পিৎজা বানালো (ছবি ৭):
আপনার বন্ধু আরো বললো যে, তাঁর পিৎজার দোকানেই অনেক জায়গা। আলাদা করে আর ফ্যাক্টরি থেকে পিৎজা বানানোর দরকার নাই। আপনিও আসলে ইদানিং ব্যবসা ভালো হওয়ায় ভাবছিলেন, নতুন বড় দোকান খুলবেন। আর সেই দোকানেই পিৎজা বানানোর ব্যবস্থা রাখবেন, কেননা কাস্টমারেরা দোকানেই ফ্রেশ পিৎজা বানানো হচ্ছে, এইটা দেখতে পছন্দ করবে। তাহলে কোডে কী করা যায়? ভেবে ঠিক করলেন, আলাদা ফ্যাক্টরিতে পিৎজা না বানিয়ে এলাকা ভিত্তিক দোকানেই পিৎজা বানানোর সুবিধা বা অনুমুতি আপনার বন্ধু বা সাবঅরডিনেট (সাবক্লাস) কে দিবেন। তবে পিৎজা অর্ডার নেয়ার প্রসেসটা আগেরটাই থাকবে। অর্থ্যাৎ, সবাই যে যার দোকানে একপাশে নিজেরাই পিৎজা বানানোর ব্যবস্থা বা মেথড চালু করবে আর মূল অর্ডার নেয়ার প্রসেসটা আগেরটাই থাকবে, চলুন কোডটা দেখি (ছবি ৮):
কি হল ব্যাপারটা? ভেবে দেখুন, আসলে পিৎজা বানানোর দায়িত্ব নিজের কাছে না রেখে এলাকা ভিত্তিক সাবক্লাসে ঠেলে দিলেন। সিলেটি পিৎজা ঘর এখন নিজেরাই নিজেদের দোকানে createPizza(String type) ইমপ্লিমেন্ট করে পিৎজা বানাবে (ছবি ৯):
এতে লাভ কি হলো? সেই আবার Separation of concern! সিলেটি পিৎজা ঘর সুপার ক্লাস থেকে orderPizza(String type) ব্যবহার করে অর্ডার নেবে ঠিকই, কিন্তু ভিন্ন স্বাদের পিৎজা বানাবে নিজেরাই। শুধু তাই না, যদি কোনো স্পেশাল পিৎজা টাইপ অফার করতে চায়, যেমন কে জানে? ‘লন্ডনি পিৎজা’ — তখনও কোড শুধু সিলেটি পিৎজা ঘরেই বদলাবে। আমাদের মূল ঢাকাইয়া পিৎজা ঘর একই থাকবে।
আচ্ছা, আমাদের মূল পিৎজা ঘরের কোডের কি অবস্থা? কি পরিবর্তন হলো? ছবি ৪, ৬ আর নিচের ছবি ১০ খেয়াল করে দেখলে দেখবেন, createPizza(String type) আবার দোকানে ফিরে এসেছে, আর orderPizza(String type) কে ধাক্কা দিয়ে সুপার ক্লাসে পাঠিয়ে দেয়া হয়েছে, দেখতে একেবারেই সিলেটি পিৎজা ঘরের মতোই, তফাৎ শুধু পিৎজাতে (ছবি ১০) :
তাহলে, ফ্যাক্টরি মেথড (Factory Method) ডিসাইন প্যাটার্ন -এর মূল আইডিয়া কি দাঁড়াচ্ছে? চলেন, Head First Design Patterns বই থেকে ফর্মাল সংজ্ঞা দেখে নেই (ছবি ১১):
আশা করি বোঝা গেলো। পুরো ফ্যাক্টরি মেথড ডিসাইন প্যাটার্নের কোড, টেস্ট ড্রাইভ কোড সহ এই Repl.it লিংকে দেয়া আছে, দেখে নিতে পারেন।
অ্যাবস্ট্রাক্ট ফ্যাক্টরি ডিসাইন প্যাটার্ন:
আজকে আর লিখছি না। পরে কোনো একটা ব্লগ পোস্টে এটা আলোচনা করবো। শুধু এই ডিসাইন প্যাটার্ন কি সমস্যার সমাধান করে সেটার একটা হিন্টস দিয়ে দেই।
ধরা যাক, আপনার সিলেটি বন্ধু মহা খুশিতে আপনার “পিৎজা ঘর” শাখা সিলেটে খুলে ভালোই ব্যবসা চালু করে দিয়েছেন। আপনাকেও লাভের অংশ ঠিক মতোই দিচ্ছেন। ভালোই চলছিল, কিন্তু হটাৎ একদিন খবর পেলেন, আপনার বন্ধুর দোকানের (ফ্যাক্টরির) ম্যানেজার একটু বেশি লাভের আশায় পিৎজার বানানোর রুটি, চিজ আর টপিংস গুলো খারাপ দেয়া শুরু করেছে। ফ্যাক্টরিতে বাজারের খারাপ কোয়ালিটির সস্তা কাঁচামাল যেমন: ময়দা, দুধ, ডিম ইত্যাদি দিয়ে পিৎজার উপকরণ বানিয়ে দিচ্ছে, তাতে পিৎজার মান কমে যাওয়ায় আপনার “পিৎজা ঘর” ব্রান্ডের দুর্নাম হতে যাচ্ছে! মহা মুশকিল তো! এখন কি করবেন আপনি?
বন্ধুকে ফোন করে না হয় বলে দিলেন একটু খেয়াল রাখতে। কিন্তু তাতে তো কাজ নাও হতে পারে। এইদিকে আপনার নোয়াখালীর এক বন্ধুও নোয়াখালীতে “পিৎজা ঘর” -এর একটা শাখা খুলতে চাচ্ছে। সব শাখাতেই পিৎজার কোয়ালিটি নিশ্চিত করবেন কিভাবে? কিভাবে সবাইকে মান ঠিক রাখতে বাধ্য করবেন? উত্তরটা নিচে দেখে নেয়ার আগে একটু থেমে নিজে ভেবে দেখুন তো।
ভেবেছেন? তাহলে এবার নিচের সমাধানটা পড়ে দেখুন আপনার সাথে মিলে কিনা।
একটা সহজ উপায় হচ্ছে সবাইকে বলে দেয়া যে সব শাখাতেই (বা ফ্রাঞ্চাইজিতে) একটা নির্দিষ্ট ব্র্যান্ডের রুটি বা ময়দা, চীজ আর টপিংস গুলো ব্যবহার করতে হবে। অর্থ্যাৎ, ফ্যাক্টরিতে এর বাইরে কোনো মাল ব্যবহার করে পিৎজা বানানো যাবে না। এই যে পিৎজার বানানোর উপকরণগুলো কোত্থেকে কিনতে হবে সেটাও বলে দিলেন অর্থ্যাৎ পিৎজা বানানোর কাঁচামাল আরেকটা নির্দিষ্ট ব্র্যান্ডের বা ফ্যাক্টরি থেকে কিনতে হবে, এইটা বাধ্যতামূলক করে দেয়ার আইডিয়াটাই অ্যাবস্ট্রাক্ট ফ্যাক্টরি (Abstract Factory) ডিসাইন প্যাটার্ন!
লেখাটি আমার ব্লগ থেকে থেকে নেয়া। ডিসাইন প্যাটার্ন সহ সফটওয়্যার ইঞ্জিনিয়ারিং -এর বিভিন্ন বিষয়ের উপর বাংলায় আমার অন্যান্য লেখাগুলো সেখানেই পাওয়া যাবে। ধন্যবাদ।
Originally published at http://software-engineering-notes-in-bangla.blogspot.com.