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

نمط Factory

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

يركّز نمط المصنع عملية إنشاء الكائنات في دالة واحدة. وبدلًا من توزيع malloc وتعليمة التهيئة في أنحاء برنامجك، تستدعي دالة واحدة تقرّر ما الذي ستنشئه وتُرجع كائنًا جاهزًا للاستخدام.

يكون هذا النمط قويًا بشكل خاص عند دمجه مع تعدد الأشكال. يمكن لـ factory إرجاع أنواع ملموسة مختلفة من خلال مؤشر base مشترك، مع إخفاء تفاصيل الإنشاء عن المستدعي. يطلب المستدعي ببساطة "شكلاً"، وتقرر factory ما إذا كانت ستنشئ دائرة أو مستطيلاً أو شيئًا آخر.

إليك تطبيقًا نموذجيًا للمصنع:

typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

Shape* create_shape(ShapeType type) {
    switch (type) {
        case SHAPE_CIRCLE:
            return (Shape*)create_circle(5.0);
        case SHAPE_RECTANGLE:
            return (Shape*)create_rectangle(4.0, 3.0);
        default:
            return NULL;
    }
}

يأخذ المصنع مُعرّفًا (عادةً ما يكون enum) ويستخدم عبارة switch لتحديد constructor الذي يجب استدعاؤه. ويُرجع Shape* بغضّ النظر عن النوع الفعلي الذي تم إنشاؤه. لا يحتاج المستدعي إلى معرفة شيء عن Circle أو Rectangle. فهو يعمل فقط مع النوع الأساسي:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // استدعاء متعدد الأشكال
free_shape(s);

يجعل هذا النمط إضافة أنواع جديدة أمرًا سهلًا: ما عليك سوى إضافة قيمة enum جديدة وcase جديدة في factory. يظل باقي كودك دون تغيير.

challenge icon

التحدي

سهل

لنَبْنِ مصنع Pet: نظامًا ينشئ أنواعًا مختلفة من الحيوانات الأليفة من خلال function واحدة للمصنع. بدلًا من توزيع منطق الإنشاء في أنحاء الكود، ستجمعه في مكان واحد يقرر نوع الحيوان الأليف الذي يجب إنشاؤه بناءً على معرّف الإدخال.

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

  • pet.h: عرّف تعداد PetType بالقيم PET_DOG وPET_CAT وPET_BIRD. أنشئ بنية أساسية Pet تحتوي على مؤشّر function لـspeak (يأخذ const Pet* ولا يُرجع شيئًا). صرّح عن function المصنع create_pet التي تأخذ PetType وتُرجع Pet*، بالإضافة إلى function free_pet لتنفيذ التنظيف.
  • pet.c: عرّف ثلاث بنيات ملموسة للحيوانات الأليفة، وهي Dog وCat وBird، بحيث تدمج كل منها Pet باعتباره العضو الأول. نفّذ function لـ لكل نوع:
    • تطبع الكلاب: Woof!
    • تطبع القطط: Meow!
    • تطبع الطيور: Tweet!
    أنشئ functionات constructor لكل نوع من الحيوانات الأليفة لتخصيص الذاكرة وربط function الـ المناسبة. ثم نفّذ مصنع create_pet: استخدم عبارة switch على PetType لاستدعاء constructor الصحيح وإرجاع النتيجة على هيئة Pet*. بالنسبة إلى الأنواع غير الصالحة، أرجِع NULL. نفّذ free_pet لتحرير الذاكرة المخصّصة.
  • main.c: اقرأ عددًا صحيحًا يمثّل نوع الحيوان الأليف (0 للكلب، و1 للقط، و2 للطائر). استخدم المصنع لإنشاء الحيوان الأليف المناسب، واستدعِ function الخاصة بـ الخاصة به تعدديًا من خلال مؤشّر البنية الأساسية Pet*، ثم حرّر الحيوان الأليف.

سيستقبل برنامجك إدخالًا واحدًا: عددًا صحيحًا يحدد الحيوان الأليف المراد إنشاؤه.

ناتج المثال عندما يكون الإدخال 0:

Woof!

ناتج المثال عندما يكون الإدخال 1:

Meow!

ناتج المثال عندما يكون الإدخال 2:

Tweet!

يكمن جمال نمط المصنع في أن main.c لا يحتاج إلى معرفة أي شيء عن بنيات Dog أو Cat أو Bird. فهو يعمل فقط مع النوع الأساسي Pet. تعني إضافة نوع جديد من الحيوانات الأليفة لاحقًا إضافة قيمة تعداد جديدة وحالة case جديدة في المصنع، من دون تغيير أي كود يستخدم الحيوانات الأليفة.

جرّب بنفسك

#include <stdio.h>
#include "pet.h"

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: استخدم المصنع لإنشاء الحيوان الأليف المناسب
    // Hint: حوّل الـ int إلى PetType
    
    // TODO: استدعِ دالة speak بشكل متعدد الأشكال عبر مؤشر Pet*
    
    // TODO: حرّر الحيوان الأليف
    
    return 0;
}
quiz iconاختبر نفسك

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

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

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