DEV Community

Moniruzzaman Saikat
Moniruzzaman Saikat

Posted on

ফ্যাক্টরি – একটি অবজেক্ট ক্রিয়েশনাল প্যাটার্ন

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

ফ্যাক্টরি প্যাটার্নকে একটি পাওয়ার প্লাগ অ্যাডাপ্টারের মতো করে ভাবেন। আপনি যেকোনো একটা ডিভাইস (ল্যাপটপ, ফোন, টিভি) এতে যুক্ত করেন, আর এটি সঠিক কারেন্ট সরবরাহ করে — এটা কীভাবে কাজ করছে তা নিয়ে চিন্তা করার দরকার নাই। ফ্যাক্টরি প্যাটার্নের মূল লক্ষ্য হইতেছে অবজেক্ট তৈরিকে বিজিনেস লজিক থেকে আলাদা করে ফেলা, যাতে আপনার কোড আরও ফ্লেক্সিবল, টেস্টেবল এবং সহজে রক্ষণাবেক্ষণযোগ্য হয়।

চলেন একটা উদাহরণ দেখি, ফ্যাক্টরি প্যাটার্নর যেটা ডকুমেন্ট এক্সপোর্টার নিচ্ছে।

interface Exporter {
    public function export(array $data): string;
}

class PdfExporter implements Exporter {
    public function export(array $data): string {
        return "Exporting as PDF";
    }
}

class CsvExporter implements Exporter {
    public function export(array $data): string {
        return "Exporting as CSV";
    }
}

class ExportFactory {
    public static function getExporter(string $format): Exporter {
        return match($format) {
            'pdf' => new PdfExporter(),
            'csv' => new CsvExporter(),
            default => throw new Exception("Invalid export format"),
        };
    }
}

// Usage
$exporter = ExportFactory::getExporter('csv');
echo $exporter->export([]);
Enter fullscreen mode Exit fullscreen mode

ফ্যাক্টরি প্যাটার্ন কেন ইউজ করা লাগে?

  • আপনি অবজেক্ট তৈরিকে ছেন্ট্রালাইজড করতে চান
  • আপনি কোড ডিকপল করতে চান (ক্লায়েন্ট জানবে না যে সে কোন ক্লাস ব্যবহার করছে)
  • ক্লায়েন্ট কোড টাচ না করেই আপনি কোন অবজেক্ট তৈরি করা হয়েছে তা পরিবর্তন করার ফ্লেক্সিবিলিটি চান

এখানে একটি নোটিফিকেশন সেন্ডার (ইমেল, এসএমএস, পুশ, যাই হোক না কেন) সিস্টেমের আরেকটি উদাহরণ দেওয়া হল:

interface Notifier {
    public function send(string $message): string;
}

class EmailNotifier implements Notifier {
    public function send(string $message): string {
        return "Sending Email: $message";
    }
}

class SMSNotifier implements Notifier {
    public function send(string $message): string {
        return "Sending SMS: $message";
    }
}

class PushNotifier implements Notifier {
    public function send(string $message): string {
        return "Sending Push Notification: $message";
    }
}

class NotificationFactory {
    public static function create(string $type): Notifier {
        return match($type) {
            'email' => new EmailNotifier(),
            'sms' => new SMSNotifier(),
            'push' => new PushNotifier(),
            default => throw new Exception("Invalid notifier type"),
        };
    }
}

// Usage
$notifier = NotificationFactory::create('sms');
echo $notifier->send('Factory pattern rocks!');
Enter fullscreen mode Exit fullscreen mode

হাহা, এখন চলেন একটা গল্প পড়ি যাতে বুঝতে আরো সুবিধা হয়, ঠিক আছে?

ছোট্ট টেকনোলজি টাউন ছিল, যেখানে সৈকত নামে এক জন বাচ্চা প্রোগ্রামার থাকতো। আর হালায় একটা পপুলার রেস্টুরেন্ট “কোড ক্রাস্ট পিৎজা”র জন্য অনলাইন ফুড অর্ডারিং সিস্টেম বানাইতেছিল।

কিন্তু প্রতি বার যখন কাস্টমার মার্গারিটা, পেপারোনি বা ভেজি পিৎজা অর্ডার দিত, সৈকতের অ্যাপের কাজ হইত এরকম:

$margherita = new MargheritaPizza();
$pepperoni = new PepperoniPizza();
$veggie = new VeggiePizza();
Enter fullscreen mode Exit fullscreen mode

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

ওওওওঁ, একটা আইডিয়া আসল, ধরেন যদি আমি কাউকে সব নতুন পিৎজা বানানোর কাজ দিয়ে দিই (মোটামুটি সব প্রসেস), আর ক্লায়েন্ট সাইড থেকে সেটা খুব সহজে ইউজ করতে পারি! তখনই ভাবল একটা PizzaFactory বানানো যাক — যে বুদ্ধিমান(হাহা) রান্নাঘরের সহকারী, যাকে বলে দিলেই যেকোন পিৎজা তৈরী করতে পারে।

আর এখানে হল সেইটা:

interface Pizza {
    public function prepare(): string;
    public function deliverd(): boolean;
}

class MargheritaPizza implements Pizza {
    public function prepare() {
        return "Preparing Margherita Pizza";
    }
}

class PepperoniPizza implements Pizza {
    public function prepare() {
        return "Preparing Pepperoni Pizza";
    }
}

class PizzaFactory {
    public static function make(string $type): Pizza {
        return match($type) {
            'margherita' => new MargheritaPizza(),
            'pepperoni'  => new PepperoniPizza(),
            default => throw new Exception("Pizza type not found"),
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

আর ইউজ করার ধরনটা এমন (স্রেফ কাস্টমারের অর্ডার করা পিৎজার নামটা পাস করো, বাকিটা ফ্যাক্টরি নিজেই করে ফেলে দিয়ে দিবে, দারুন):

$pizza = PizzaFactory::make('pepperoni');
echo $pizza->prepare();
echo $pizza->deliverd(); // shanti shanti shanti
Enter fullscreen mode Exit fullscreen mode

আর কোথাও new ClassName() দিয়ে দিয়ে প্যারা খাওয়া লাগবে না। কিচেন (ফ্যাক্টরি) নিজের মতো করে সব সামলায়, আর সৈকত পেয়ে যায় শান্তি :)

মোরাল অব দা স্টোরিঃ

ফ্যাক্টরি প্যাটার্ন একদম রেস্টুরেন্টের রান্নাঘরেরই মতো — ক্লায়েন্টরা (সৈকতের অ্যাপ) সরাসরি খাবার বানায় না। তারা রান্নাঘরের (ফ্যাক্টরির) কাছে যায়, আর রান্নাঘর সঠিক ডিশ বানায়ে বানায়ে পরিবেশন করে।

Top comments (1)

Collapse
 
samsamimz profile image
SaMim Rahman

xoss xoss