תבנית Factory
חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 72 מתוך 91.
תבנית המפעל היא תבנית עיצוב ליצירה שמעבירה את יצירת האובייקטים למחלקה או למתודה נפרדת. במקום להשתמש ב-new ישירות בכל הקוד, מבקשים ממפעל ליצור עבורכם אובייקטים.
תבנית זו שימושית במיוחד כשיש לך כמה מחלקות קשורות שחולקות ממשק משותף, ואתה רוצה להחליט איזו מהן ליצור בהתאם לתנאי מסוים. נבחן מערכת התראות שיכולה לשלוח הודעות בערוצים שונים:
<?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";
}
}
בלי מפעל, היית מפזר הצהרות if וקריאות new בכל מקום. המפעל מרכז את הלוגיקה הזאת:
<?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, ולא במחלקות קונקרטיות. אם בהמשך תוסיף מחלקה בשם PushNotification, תצטרך לעדכן רק את המפעל. כל הקוד שמשתמש במפעל יקבל אוטומטית גישה לסוג החדש, ללא שינויים.
אתגר
קלנבנה מערכת ליצירת מסמכים באמצעות תבנית Factory. סוגי מסמכים שונים (PDF, HTML, טקסט פשוט) חולקים ממשק משותף, אך מפיקים פלטים שונים: זהו תרחיש מושלם לריכוז יצירת האובייקטים במפעל.
תארגנו את הקוד שלכם בארבעה קבצים:
Document.php: צרו ממשקDocumentשמגדיר את החוזה שכל סוגי המסמכים חייבים לקיים. צריכה להיות בו מתודה יחידהrender(string $content): stringשמקבלת תוכן ומחזירה את פלט המסמך המעוצב.Documents.php: כללו את ממשק Document וצרו שלוש מחלקות שמממשות אותו:PdfDocument: המתודהrender()שלה מחזירה"PDF: [content]"HtmlDocument: המתודהrender()שלה מחזירה"<html>[content]</html>"TextDocument: המתודהrender()שלה מחזירה"TXT: [content]"
DocumentFactory.php: כללו את קובץ Documents וצרו מחלקתDocumentFactoryעם מתודה סטטיתcreate(string $type): Document. המתודה צריכה להשתמש ב-matchכדי להחזיר את אובייקט המסמך המתאים לפי הסוג:"pdf"מחזיר אובייקט חדש שלPdfDocument"html"מחזיר אובייקט חדש שלHtmlDocument"text"מחזיר אובייקט חדש שלTextDocument- כל סוג אחר צריך לגרום לזריקת
InvalidArgumentExceptionעם ההודעה"Unknown document type: [type]"
main.php: כללו את קובץ DocumentFactory. תקבלו שתי קלטים: סוג מסמך והתוכן לעיבוד.השתמשו במפעל כדי ליצור את סוג המסמך המתאים, ואז קראו למתודה
render()שלו עם התוכן והדפיסו את התוצאה.בשורה חדשה, הדפיסו
"Factory benefit: Adding new types only requires updating the factory"כדי להדגיש מדוע התבנית הזו שימושית.
תבנית Factory משאירה את הקוד שלכם גמיש: כשתצטרכו להוסיף בהמשך MarkdownDocument, תצטרכו לעדכן רק את המפעל, בעוד שכל הקוד הקיים ימשיך לעבוד ללא שינוי.
נסו בעצמכם
<?php
require_once 'DocumentFactory.php';
// קרא את הקלט
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
// TODO: השתמש ב-DocumentFactory כדי ליצור את סוג המסמך המתאים
// TODO: קרא למתודה render() עם התוכן והדפס את התוצאה
// TODO: בשורה חדשה, הדפס "Factory benefit: Adding new types only requires updating the factory"
?>השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח $thisמתודותמאפייניםבנאי (__construct)הורס (__destruct)חזרה: מחשבון פשוט4ירושה
ירושה בסיסיתמילת המפתח parent::דריסת מתודותמילת המפתח finalמחלקות מופשטותסיכום – היררכיית עובדים7כימוס
ציבורי, מוגן, פרטימפרטי גישה לעומקמתודות גישה ועדכוןהסתרת מידעקידום פרמטרים בבנאי (8.0)סיכום – מערכת רישומי תלמידים2מרחבי שמות וטעינה אוטומטית
מבוא למרחבי שמותמילת המפתח useתקן הטעינה האוטומטית PSR-4הטוען האוטומטי של Composerסיכום – פרויקט מאורגן5ממשקים וחוזים
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםממשק לעומת מחלקה מופשטתרמזי טיפוסים עם ממשקיםסיכום - מחשבון צורות8מתודות קסם
מבוא למתודות קסם__toString ו־__debugInfo__get, __set, __isset, __unset__call ו־__callStatic__clone ושיבוט אובייקטים__serialize ו־__unserializeסיכום – אוסף מותאם אישית3מאפייני מחלקה
מאפייני מופע לעומת מאפיינים סטטייםקבועים במחלקותמתודות ומאפיינים סטטייםמאפיינים פרטיים ומוגניםמאפיינים לקריאה בלבד (PHP 8.1)סיכום – מנהל חשבון בנק6פולימורפיזם
בחינה מחדש של דריסת מתודותפולימורפיזם באמצעות ממשקיםרמזי טיפוסים וטיפוסי איחודקישור סטטי מאוחרסיכום — מעבד תשלומיםתרגלו בעצמכם: קומפיילר PHP אונליין