ওহে! আজ আমরা ডিজাইন প্যাটার্ন অধ্যয়ন চালিয়ে যাব এবং আমরা ফ্যাক্টরি পদ্ধতির প্যাটার্ন নিয়ে আলোচনা করব। আপনি এটি কী এবং এই প্যাটার্নটি কোন কাজের জন্য উপযুক্ত তা খুঁজে পাবেন। আমরা অনুশীলনে এই নকশা প্যাটার্ন বিবেচনা করব এবং এর গঠন অধ্যয়ন করব। সবকিছু পরিষ্কার নিশ্চিত করতে, আপনাকে নিম্নলিখিত বিষয়গুলি বুঝতে হবে:
- জাভাতে উত্তরাধিকার।
- জাভাতে বিমূর্ত পদ্ধতি এবং ক্লাস
কারখানা পদ্ধতি কি সমস্যা সমাধান করে?
সমস্ত ফ্যাক্টরি ডিজাইনের প্যাটার্নে দুই ধরনের অংশগ্রহণকারী থাকে: নির্মাতা (কারখানা নিজেরাই) এবং পণ্য (ফ্যাক্টরি দ্বারা তৈরি বস্তু)। নিম্নলিখিত পরিস্থিতিটি কল্পনা করুন: আমাদের একটি কারখানা রয়েছে যা কোডজিম-ব্র্যান্ডেড গাড়ি তৈরি করে। এটি বিভিন্ন ধরণের দেহ সহ গাড়ির মডেলগুলি কীভাবে তৈরি করতে হয় তা জানে:- সেডান
- স্টেশন ওয়াগন
- কুপস
- কোডজিম সেডান
- কোডজিম স্টেশন ওয়াগন
- কোডজিম কুপস
- ওয়ানঅটো সেডান
- ওয়ানঅটো স্টেশন ওয়াগন
- OneAuto coupes
কারখানা প্যাটার্ন সম্পর্কে বিট
আমি আপনাকে মনে করিয়ে দিই যে আমরা আগে একটি ছোট ভার্চুয়াল কফি শপ তৈরি করেছি। একটি সাধারণ কারখানার সাহায্যে আমরা শিখেছি কিভাবে বিভিন্ন ধরনের কফি তৈরি করতে হয়। আজ আমরা এই উদাহরণটি পুনরায় কাজ করব। আসুন মনে করি আমাদের কফি শপটি তার সাধারণ কারখানা সহ দেখতে কেমন ছিল। আমাদের একটি কফি ক্লাস ছিল:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
এবং আমাদের ফ্যাক্টরি তৈরি করতে পারে এমন নির্দিষ্ট ধরণের কফির সাথে সম্পর্কিত বেশ কয়েকটি শিশু ক্লাস:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
অর্ডার দেওয়া সহজ করার জন্য আমরা একটি enum তৈরি করেছি:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
কফি কারখানা নিজেই এই মত দেখায়:
public class SimpleCoffeeFactory {
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappuccino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
এবং অবশেষে, কফি শপ নিজেই দেখতে এইরকম ছিল:
public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
একটি সাধারণ কারখানার আধুনিকায়ন
আমাদের কফি শপ খুব ভালো চলছে। এতটাই যে আমরা সম্প্রসারণের কথা ভাবছি। আমরা কিছু নতুন অবস্থান খুলতে চাই. আমরা সাহসী এবং উদ্যোগী, তাই আমরা বিরক্তিকর কফি শপগুলিকে ক্র্যাঙ্ক করব না। আমরা চাই প্রতিটি দোকানে একটি বিশেষ টুইস্ট থাকুক। তদনুসারে, শুরু করার জন্য, আমরা দুটি অবস্থান খুলব: একটি ইতালীয় এবং একটি আমেরিকান৷ এই পরিবর্তনগুলি শুধুমাত্র অভ্যন্তর নকশাই নয়, প্রস্তাবিত পানীয়গুলিকেও প্রভাবিত করবে:- ইতালীয় কফি শপে, আমরা বিশেষভাবে গ্রাইন্ডিং এবং রোস্টিং সহ একচেটিয়াভাবে ইতালিয়ান কফি ব্র্যান্ডগুলি ব্যবহার করব৷
- আমেরিকান অবস্থানে বড় অংশ থাকবে, এবং আমরা প্রতিটি অর্ডারের সাথে মার্শম্যালো পরিবেশন করব।
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
কিন্তু এখন আমাদের 8 থাকবে:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}
public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
যেহেতু আমরা বর্তমান ব্যবসায়িক মডেল রাখতে চাই, তাই আমরা চাই orderCoffee(CoffeeType type)
পদ্ধতিতে যতটা সম্ভব কম পরিবর্তন করা হোক। এটি একবার দেখুন:
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
আমাদের কি বিকল্প আছে? আচ্ছা, আমরা ইতিমধ্যে জানি কিভাবে একটি কারখানা লিখতে হয়, তাই না? সবচেয়ে সহজ জিনিস যা অবিলম্বে মনে আসে তা হল দুটি অনুরূপ কারখানা লিখুন এবং তারপরে আমাদের কফি শপের কনস্ট্রাক্টরের কাছে পছন্দসই বাস্তবায়নটি পাস করুন। এতে করে কফি শপের শ্রেণী পরিবর্তন হবে না। প্রথমত, আমাদের একটি নতুন ফ্যাক্টরি ক্লাস তৈরি করতে হবে, এটিকে আমাদের সাধারণ কারখানার উত্তরাধিকারী করতে হবে এবং তারপর createCoffee(CoffeeType type)
পদ্ধতিটিকে ওভাররাইড করতে হবে। ইতালীয়-শৈলী কফি এবং আমেরিকান-শৈলী কফি তৈরির কারখানা লিখুন:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
এখন আমরা কাঙ্খিত ফ্যাক্টরি বাস্তবায়ন কফিশপে পাস করতে পারি। চলুন দেখি বিভিন্ন কফি শপ থেকে কফি অর্ডার করার কোড কেমন হবে। উদাহরণস্বরূপ, ইতালীয়-শৈলী এবং আমেরিকান-শৈলী ক্যাপুচিনো:
public class Main {
public static void main(String[] args) {
/*
Order an Italian-style cappuccino:
1. Create a factory for making Italian coffee
2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
3. Order our coffee
*/
SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
/*
Order an American-style cappuccino
1. Create a factory for making American coffee
2. Create a new coffee shop, passing the American coffee factory to it through the constructor
3. Order our coffee
*/
SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
}
}
আমরা দুটি আলাদা কফি শপ তৈরি করেছি, প্রতিটিতে কাঙ্খিত ফ্যাক্টরি পাস করেছি। একদিকে, আমরা আমাদের উদ্দেশ্য পূরণ করেছি, কিন্তু অন্যদিকে... কোনভাবে এটি উদ্যোক্তাদের সাথে ভালভাবে বসে না... চলুন খুঁজে বের করা যাক কী ভুল। প্রথমত, কারখানার প্রাচুর্য। কি? এখন প্রতিটি নতুন অবস্থানের জন্য, আমাদের নিজস্ব কারখানা তৈরি করতে হবে এবং তা ছাড়াও, নিশ্চিত করুন যে একটি কফি শপ তৈরি করার সময় প্রাসঙ্গিক কারখানাটি কনস্ট্রাক্টরের কাছে পাঠানো হয়েছে? দ্বিতীয়ত, এটি এখনও একটি সাধারণ কারখানা। শুধু সামান্য আধুনিকীকরণ. কিন্তু আমরা এখানে একটি নতুন প্যাটার্ন শিখতে এসেছি। তৃতীয়ত, একটি ভিন্ন পদ্ধতি কি সম্ভব নয়? আমরা যদি কফি তৈরির সাথে সম্পর্কিত সমস্ত সমস্যাগুলি রাখতে পারি তবে এটি দুর্দান্ত হবেCoffeeShop
কফি তৈরি এবং সার্ভিসিং অর্ডারের প্রক্রিয়াগুলিকে সংযুক্ত করে ক্লাস, একই সাথে বিভিন্ন শৈলী কফি তৈরির জন্য যথেষ্ট নমনীয়তা বজায় রাখা। উত্তর হল হ্যাঁ, আমরা পারি। একে ফ্যাক্টরি মেথড ডিজাইন প্যাটার্ন বলা হয়।
একটি সাধারণ কারখানা থেকে একটি কারখানা পদ্ধতিতে
যতটা সম্ভব দক্ষতার সাথে কাজটি সমাধান করতে:- আমরা
createCoffee(CoffeeType type)
পদ্ধতিটি ক্লাসে ফিরিয়ে দিইCoffeeShop
। - আমরা এই পদ্ধতিটি বিমূর্ত করব।
- ক্লাস
CoffeeShop
নিজেই বিমূর্ত হয়ে যাবে। - ক্লাসে
CoffeeShop
চাইল্ড ক্লাস থাকবে।
CoffeeShop
, যা createCoffee(CoffeeType type)
ইতালীয় বারিস্তাদের সেরা ঐতিহ্য অনুসারে পদ্ধতিটি প্রয়োগ করে। এখন, এক সময়ে এক ধাপ। ধাপ 1. Coffee
ক্লাস বিমূর্ত করুন। আমরা বিভিন্ন পণ্য দুটি সম্পূর্ণ পরিবার আছে. তবুও, ইতালীয় এবং আমেরিকান কফির একটি সাধারণ পূর্বপুরুষ রয়েছে - শ্রেণী Coffee
। এটি বিমূর্ত করা সঠিক হবে:
public abstract class Coffee {
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
ধাপ 2. একটি বিমূর্ত পদ্ধতির CoffeeShop
সাহায্যে বিমূর্ত তৈরি করুনcreateCoffee(CoffeeType type)
public abstract class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = createCoffee(type);
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
protected abstract Coffee createCoffee(CoffeeType type);
}
ধাপ 3. একটি ইতালীয় কফি শপ তৈরি করুন, যা বিমূর্ত কফি শপের একটি বংশধর। আমরা createCoffee(CoffeeType type)
ইতালীয় রেসিপিগুলির সুনির্দিষ্ট বৈশিষ্ট্যগুলি বিবেচনায় নিয়ে এটিতে পদ্ধতিটি প্রয়োগ করি।
public class ItalianCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
ধাপ 4. আমরা আমেরিকান-স্টাইলের কফি শপের জন্য একই কাজ করি
public class AmericanCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
ধাপ 5. আমেরিকান এবং ইতালীয় ল্যাটেস দেখতে কেমন হবে তা দেখুন:
public class Main {
public static void main(String[] args) {
CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
}
}
অভিনন্দন। আমরা উদাহরণ হিসাবে আমাদের কফি শপ ব্যবহার করে কারখানা পদ্ধতির নকশা প্যাটার্নটি প্রয়োগ করেছি।
কারখানা পদ্ধতির পিছনে নীতি
এখন আমরা কী পেয়েছি তা আরও বিশদে বিবেচনা করা যাক। নীচের চিত্রটি ফলস্বরূপ ক্লাসগুলি দেখায়। সবুজ ব্লক হল সৃষ্টিকর্তার ক্লাস, এবং নীল ব্লক হল প্রোডাক্ট ক্লাস। আমরা কি সিদ্ধান্ত নিতে পারি?- সমস্ত পণ্য বিমূর্ত শ্রেণীর বাস্তবায়ন
Coffee
. - সমস্ত নির্মাতাই বিমূর্ত শ্রেণীর বাস্তবায়ন
CoffeeShop
। - আমরা দুটি সমান্তরাল শ্রেণীর শ্রেণিবিন্যাস দেখতে পাই:
- পণ্যের শ্রেণিবিন্যাস। আমরা ইতালীয় বংশধর এবং আমেরিকান বংশধরদের দেখতে পাই
- সৃষ্টিকর্তাদের অনুক্রম। আমরা ইতালীয় বংশধর এবং আমেরিকান বংশধরদের দেখতে পাই
- কোন নির্দিষ্ট পণ্য ( ) তৈরি করা হবে সে সম্পর্কে সুপারক্লাসের
CoffeeShop
কোনো তথ্য নেই ।Coffee
- সুপারক্লাস
CoffeeShop
একটি নির্দিষ্ট পণ্য তৈরির দায়িত্ব তার বংশধরদেরকে অর্পণ করে। - শ্রেণীর প্রতিটি বংশধর তার নিজস্ব নির্দিষ্ট বৈশিষ্ট্য অনুযায়ী
CoffeeShop
একটি কারখানা পদ্ধতি প্রয়োগ করে ।createCoffee()
অন্য কথায়, প্রযোজক শ্রেণীর বাস্তবায়ন প্রযোজক শ্রেণীর নির্দিষ্টতার উপর ভিত্তি করে নির্দিষ্ট পণ্য প্রস্তুত করে।
একটি কারখানা পদ্ধতির গঠন
উপরের চিত্রটি কারখানা পদ্ধতির প্যাটার্নের সাধারণ কাঠামো দেখায়। এখানে গুরুত্বপূর্ণ আর কি?- নির্মাতা শ্রেণী কারখানা পদ্ধতি ছাড়া পণ্যের সাথে ইন্টারঅ্যাক্ট করে এমন সমস্ত পদ্ধতি প্রয়োগ করে।
- বিমূর্ত
factoryMethod()
পদ্ধতিটি অবশ্যই ক্লাসের সমস্ত বংশধরদের দ্বারা প্রয়োগ করা উচিতCreator
। - ক্লাস পদ্ধতিটি
ConcreteCreator
প্রয়োগ করেfactoryMethod()
, যা সরাসরি পণ্য তৈরি করে। - এই শ্রেণীর নির্দিষ্ট পণ্য তৈরির জন্য দায়ী. এই পণ্যগুলি তৈরি করার তথ্য সহ এটিই একমাত্র ক্লাস।
- সমস্ত পণ্য একটি সাধারণ ইন্টারফেস প্রয়োগ করতে হবে, অর্থাৎ তারা একটি সাধারণ পণ্য শ্রেণীর বংশধর হতে হবে। এটি প্রয়োজনীয় যাতে পণ্যগুলি ব্যবহার করে এমন ক্লাসগুলি নির্দিষ্ট বাস্তবায়নের পরিবর্তে বিমূর্ততা হিসাবে তাদের উপর কাজ করতে পারে।
GO TO FULL VERSION