Menu
Coddy logo textTech

תבנית Factory

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 87 מתוך 107.

תבנית Factory מעבירה את יצירת האובייקטים לפונקציה או למתודה נפרדת, ומאפשרת לך ליצור מופעים בלי לחשוף את לוגיקת היצירה. בניגוד ל-Singleton, ששולטת במספר המופעים, Factory מתמקדת ביצירה גמישה של אובייקטים על סמך פרמטרי הקלט.

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

type Notifier interface {
    Send(message string) string
}

type EmailNotifier struct{}
type SMSNotifier struct{}

func (e EmailNotifier) Send(message string) string {
    return "Email: " + message
}

func (s SMSNotifier) Send(message string) string {
    return "SMS: " + message
}

func NewNotifier(notifierType string) Notifier {
    switch notifierType {
    case "email":
        return EmailNotifier{}
    case "sms":
        return SMSNotifier{}
    default:
        return EmailNotifier{}
    }
}

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

notifier := NewNotifier("sms")
result := notifier.Send("Hello!")  // "SMS: Hello!"

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

challenge icon

אתגר

קל

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

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

  • converter.go: הגדירו את ממשק הממיר ואת המימושים הקונקרטיים.

    צרו ממשק Converter עם מתודה Convert(content string) string שמקבלת את תוכן המסמך ומחזירה את הפלט שהומר.

    ממשו שלושה סוגי ממירים:

    • PDFConverter: המתודה Convert שלו מחזירה PDF: [content]
    • HTMLConverter: המתודה Convert שלו מחזירה HTML: <p>[content]</p>
    • MarkdownConverter: המתודה Convert שלו מחזירה MD: # [content]

    צרו פונקציית factory בשם NewConverter(format string) Converter שמחזירה את הממיר המתאים בהתאם למחרוזת הפורמט (pdf, html או markdown). עבור כל פורמט לא מזוהה, החזירו PDFConverter כברירת מחדל.

  • main.go: השתמשו ב-factory כדי ליצור ממירים ולעבד מסמכים.

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

הקלטים הבאים יסופקו:

  • שורה 1: סוג הפורמט (pdf, html, markdown או משהו אחר)
  • שורה 2: תוכן המסמך להמרה

לדוגמה, עבור:

html
Welcome to Go Programming

הפלט שלכם אמור להיות:

HTML: <p>Welcome to Go Programming</p>

ועבור:

markdown
Chapter One

הפלט שלכם אמור להיות:

MD: # Chapter One

ועבור:

pdf
Annual Report 2024

הפלט שלכם אמור להיות:

PDF: Annual Report 2024

ועבור:

docx
Meeting Notes

הפלט שלכם אמור להיות:

PDF: Meeting Notes

שימו לב שהקוד הראשי לא צריך להכיר את סוגי הממירים הספציפיים. הוא פשוט מבקש ממיר מה-factory ומשתמש בממשק. כך קל להוסיף פורמטים חדשים בהמשך בלי לשנות את קוד הלקוח!

נסו בעצמכם

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// קרא את סוג הפורמט
	scanner.Scan()
	format := scanner.Text()
	
	// קרא את תוכן המסמך
	scanner.Scan()
	content := scanner.Text()
	
	// TODO: השתמש במפעל ליצירת הממיר המתאים
	// TODO: המר את התוכן והדפס את התוצאה
	
	fmt.Println(result)
}
quiz iconבחנו את עצמכם

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

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

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