Menu
Coddy logo textTech

תבנית Factory

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 91 מתוך 110.

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

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

abstract class Notification {
  void send(String message);
}

class EmailNotification implements Notification {
  @override
  void send(String message) => print('Email: $message');
}

class SMSNotification implements Notification {
  @override
  void send(String message) => print('SMS: $message');
}

class NotificationFactory {
  static Notification create(String type) {
    switch (type) {
      case 'email':
        return EmailNotification();
      case 'sms':
        return SMSNotification();
      default:
        return EmailNotification();
    }
  }
}

void main() {
  var notification = NotificationFactory.create('sms');
  notification.send('Hello!');  // SMS: Hello!
}

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

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

challenge icon

אתגר

קל

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

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

  • document_factory.dart: צרו כאן את מערכת המסמכים:
    • מחלקה מופשטת Document עם מתודה generate(String content) שמחזירה String
    • שלוש מחלקות קונקרטיות שמממשות את Document:
      • Report - המתודה generate שלה מחזירה === REPORT ===\n[content]\n=============
      • Invoice - המתודה generate שלה מחזירה INVOICE\n--------\n[content]\nTotal Due
      • Letter - המתודה generate שלה מחזירה Dear Reader,\n[content]\nSincerely
    • מחלקה DocumentFactory עם מתודה סטטית create(String type) שמחזירה את Document המתאים על סמך מחרוזת הסוג: "report", "invoice" או "letter". עבור כל סוג לא מוכר, החזירו Letter כברירת מחדל
  • main.dart: ייבאו את מפעל המסמכים והדגימו כיצד המפעל יוצר סוגים שונים של מסמכים בלי שהלקוח יצטרך להכיר את המחלקות הקונקרטיות:
    • השתמשו במפעל כדי ליצור דוח והדפיסו את התוצאה של יצירתו עם התוכן Sales increased by 25%
    • הדפיסו שורה ריקה
    • השתמשו במפעל כדי ליצור חשבונית והדפיסו את התוצאה של יצירתה עם התוכן Widget x3 - $150
    • הדפיסו שורה ריקה
    • השתמשו במפעל כדי ליצור מכתב והדפיסו את התוצאה של יצירתו עם התוכן Thank you for your order

שימו לב שקובץ ה-main שלכם מתקשר רק עם המפעל ועם הטיפוס המופשט Document - הוא אף פעם לא יוצר ישירות אובייקטים של Report, Invoice או Letter!

הפלט הצפוי:

=== REPORT ===
Sales increased by 25%
=============

INVOICE
--------
Widget x3 - $150
Total Due

Dear Reader,
Thank you for your order
Sincerely

נסו בעצמכם

import 'document_factory.dart';

void main() {
  // TODO: השתמשו ב-DocumentFactory.create() כדי ליצור דוח
  // לאחר מכן הדפיסו את תוצאת יצירתו עם התוכן: "Sales increased by 25%"
  
  // TODO: הדפיסו שורה ריקה
  
  // TODO: השתמשו ב-DocumentFactory.create() כדי ליצור חשבונית
  // לאחר מכן הדפיסו את תוצאת יצירתה עם התוכן: "Widget x3 - \$150"
  
  // TODO: הדפיסו שורה ריקה
  
  // TODO: השתמשו ב-DocumentFactory.create() כדי ליצור מכתב
  // לאחר מכן הדפיסו את תוצאת יצירתו עם התוכן: "Thank you for your order"
}
quiz iconבחנו את עצמכם

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

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

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