Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط Factory

جزء من قسم البرمجة كائنية التوجه في رحلة PHP على Coddy. الدرس 72 من 91.

إن نمط Factory هو نمط تصميم إنشائي يفوّض إنشاء الكائنات إلى فئة أو method منفصلة. بدلًا من استخدام new مباشرةً في جميع أنحاء التعليمات البرمجية، تطلب من factory إنشاء الكائنات نيابةً عنك.

يكون هذا النمط مفيدًا بشكل خاص عندما تكون لديك عدة أصناف مترابطة تشترك في interface مشترك، وتريد تحديد أيٍّ منها سيتم إنشاء مثيل له استنادًا إلى شرط معيّن. تأمل نظام notification يمكنه send message عبر قنوات مختلفة:

<?php
interface Notification {
    public function send(string $message): string;
}

class EmailNotification implements Notification {
    public function send(string $message): string {
        return "Email: $message";
    }
}

class SmsNotification implements Notification {
    public function send(string $message): string {
        return "SMS: $message";
    }
}

من دون factory، ستبعثر عبارات if واستدعاءات new في كل مكان. يعمل factory على توحيد هذه المنطق:

<?php
class NotificationFactory {
    public static function create(string $type): Notification {
        return match($type) {
            'email' => new EmailNotification(),
            'sms' => new SmsNotification(),
            default => throw new InvalidArgumentException("Unknown type: $type")
        };
    }
}

$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');

المخرجات:

Email: Hello!

إن Notification benefit الرئيسي هو أن كودك يعتمد على Notification interface، وليس على classات ملموسة. إذا أضفت لاحقًا class باسم PushNotification، فلن تحتاج إلا إلى تحديث factory. ستتمكن جميع الأكواد التي تستخدم factory تلقائيًا من الوصول إلى النوع الجديد دون إجراء أي تعديل.

challenge icon

التحدي

سهل

لنبنِ نظامًا لإنشاء المستندات باستخدام نمط Factory. تشترك أنواع المستندات المختلفة (PDF وHTML والنص العادي) في interface مشترك، لكنها تنتج مخرجات مختلفة: وهذا سيناريو مثالي لمركزة إنشاء الكائنات داخل factory.

ستنظّم الكود عبر أربعة ملفات:

  • Document.php: أنشئ interface باسم Document يعرّف العقد الذي يجب أن تتبعه جميع أنواع document. وينبغي أن يحتوي على method واحدة هي render(string $content): string، تأخذ content وتُرجع مخرجات document المنسّقة.
  • Documents.php: أدرج interface الخاص بـ Document وأنشئ ثلاث class تطبّقه:
    • PdfDocument: تُرجع method الخاصة بها render() القيمة "PDF: [content]"
    • HtmlDocument: تُرجع method الخاصة بها render() القيمة "<html>[content]</html>"
    • TextDocument: تُرجع method الخاصة بها render() القيمة "TXT: [content]"
  • DocumentFactory.php: أدرج ملف Documents وأنشئ class باسم DocumentFactory مع method ثابتة هي create(string $type): Document. ينبغي أن تستخدم هذه method كلمة match لإرجاع كائن document المناسب بناءً على النوع:
    • "pdf" تُرجع كائنًا جديدًا من PdfDocument
    • "html" تُرجع كائنًا جديدًا من HtmlDocument
    • "text" تُرجع كائنًا جديدًا من TextDocument
    • يجب أن يؤدي أي نوع آخر إلى رمي InvalidArgumentException مع message هي "Unknown document type: [type]"
  • main.php: أدرج ملف DocumentFactory. ستتلقى مدخلين: نوع document وcontent المطلوب عرضه.

    استخدم factory لإنشاء نوع document المناسب، ثم استدعِ method الخاصة به render() مع content واطبع result.

    في سطر جديد، اطبع "Factory benefit: Adding new types only requires updating the factory" لتوضيح سبب أهمية هذا النمط.

يحافظ Factory Pattern على مرونة الكود، فعندما تحتاج إلى إضافة MarkdownDocument لاحقًا، ستحدّث factory فقط، بينما يستمر كل الكود الحالي في العمل دون تغيير.

جرّب بنفسك

<?php
require_once 'DocumentFactory.php';

// قراءة الإدخال
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));

// TODO: استخدم DocumentFactory لإنشاء نوع المستند المناسب
// TODO: استدعِ الدالة render() مع المحتوى واطبع النتيجة
// TODO: On a new line, print "Factory benefit: Adding new types only requires updating the factory"

?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم PHP عبر الإنترنت