Menu
Coddy logo textTech

תבנית Factory

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 55 מתוך 61.

דפוס Factory מרכז יצירת אובייקטים בפונקציה אחת. במקום לפזר את malloc ואת קוד האתחול ברחבי התוכנית שלך, קוראים לפונקציה אחת שמחליטה מה ליצור ומחזירה אובייקט מוכן לשימוש.

התבנית הזאת חזקה במיוחד בשילוב עם פולימורפיזם. מפעל יכול להחזיר טיפוסים קונקרטיים שונים דרך מצביע בסיס משותף, ולהסתיר מהקורא את פרטי היצירה. הקורא רק מבקש "צורה", והמפעל מחליט אם ליצור עיגול, מלבן או משהו אחר.

הנה מימוש טיפוסי של מפעל:

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 כדי לקבוע לאיזה בנאי לקרוא. הוא מחזיר Shape* ללא קשר לסוג שנוצר בפועל. הקוד הקורא לא צריך לדעת על Circle או על Rectangle. הוא פשוט עובד עם טיפוס הבסיס:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // קריאה פולימורפית
free_shape(s);

התבנית הזו מקלה על הוספת סוגים חדשים: פשוט מוסיפים ערך חדש ל־enum ומקרה חדש במפעל. שאר הקוד נשאר ללא שינוי.

challenge icon

אתגר

קל

בואו נבנה מפעל לחיות מחמד: מערכת שיוצרת סוגים שונים של חיות מחמד באמצעות פונקציית מפעל יחידה. במקום לפזר את לוגיקת היצירה לאורך הקוד, תרכזו אותה במקום אחד שמחליט איזה סוג של חיית מחמד ליצור על סמך מזהה קלט.

תארגנו את הקוד שלכם בשלושה קבצים:

  • pet.h: הגדירו טיפוס enum בשם PetType עם הערכים PET_DOG, PET_CAT ו-PET_BIRD. צרו מבנה בסיס בשם Pet שמכיל מצביע לפונקציה בשם speak (שמקבלת const Pet* ואינה מחזירה ערך). הצהירו על פונקציית המפעל create_pet שמקבלת PetType ומחזירה Pet*, וכן על פונקציה בשם free_pet לניקוי.
  • pet.c: הגדירו שלושה מבני חיות מחמד קונקרטיים, Dog, Cat ו-Bird, שכל אחד מהם משלב את Pet כחבר הראשון שלו. ממשו פונקציית דיבור לכל סוג:
    • כלבים מדפיסים: Woof!
    • חתולים מדפיסים: Meow!
    • ציפורים מדפיסות: Tweet!
    צרו פונקציות בנאי לכל סוג של חיית מחמד, שמקצות זיכרון ומגדירות את פונקציית הדיבור המתאימה. לאחר מכן ממשו את מפעל create_pet: השתמשו במשפט switch על PetType כדי לקרוא לבנאי המתאים ולהחזיר את התוצאה בתור Pet*. עבור טיפוסים לא תקינים, החזירו NULL. ממשו את free_pet כדי לשחרר את הזיכרון שהוקצה.
  • main.c: קראו מספר שלם שמייצג את סוג חיית המחמד (0 לכלב, 1 לחתול, 2 לציפור). השתמשו במפעל כדי ליצור את חיית המחמד המתאימה, קראו לפונקציית speak שלה באופן פולימורפי באמצעות המצביע מסוג Pet* של מבנה הבסיס, ואז שחררו את חיית המחמד.

התוכנית שלכם תקבל קלט אחד: מספר שלם המציין איזו חיית מחמד ליצור.

דוגמה לפלט כאשר הקלט הוא 0:

Woof!

דוגמה לפלט כאשר הקלט הוא 1:

Meow!

דוגמה לפלט כאשר הקלט הוא 2:

Tweet!

היתרון של תבנית המפעל הוא ש-main.c לא צריך להכיר את המבנים Dog, Cat או Bird. הוא עובד רק עם טיפוס הבסיס Pet. הוספת סוג חדש של חיית מחמד בהמשך פירושה הוספת ערך enum חדש ומקרה חדש במפעל, בלי לשנות קוד שמשתמש בחיות מחמד.

נסו בעצמכם

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

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: השתמשו בפונקציית היצירה כדי ליצור את חיית המחמד המתאימה
    // רמז: בצעו המרת טיפוס מ-int ל-PetType
    
    // TODO: קראו לפונקציה speak באופן פולימורפי דרך המצביע Pet*
    
    // TODO: שחררו את הזיכרון של חיית המחמד
    
    return 0;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C אונליין