Menu
Coddy logo textTech

דפוס Builder ב-Go

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

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

כך מיישמים builder עבור בקשת HTTP:

type Request struct {
    method  string
    url     string
    headers map[string]string
    body    string
}

type RequestBuilder struct {
    request *Request
}

func NewRequestBuilder() *RequestBuilder {
    return &RequestBuilder{
        request: &Request{
            headers: make(map[string]string),
        },
    }
}

func (b *RequestBuilder) Method(m string) *RequestBuilder {
    b.request.method = m
    return b
}

func (b *RequestBuilder) URL(u string) *RequestBuilder {
    b.request.url = u
    return b
}

func (b *RequestBuilder) Header(key, value string) *RequestBuilder {
    b.request.headers[key] = value
    return b
}

func (b *RequestBuilder) Build() *Request {
    return b.request
}

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

req := NewRequestBuilder().
    Method("POST").
    URL("https://api.example.com").
    Header("Content-Type", "application/json").
    Build()

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

challenge icon

אתגר

קל

בואו נבנה רכיב ליצירת הודעות דוא״ל באמצעות תבנית הבנאי (Builder Pattern)! להודעות דוא״ל יש רכיבים אופציונליים רבים — נמענים, עותק (CC), נושא, גוף וקבצים מצורפים — ולכן הן מתאימות במיוחד ליצירה שלב אחר שלב באמצעות שרשור מתודות.

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

  • email.go: הגדר את מבנה הנתונים של הודעת הדוא״ל שלך ואת הבנאי שלה.

    צור מבנה Email עם השדות האלה:

    • from (מחרוזת)
    • to (פרוסה של מחרוזות)
    • cc (פרוסה של מחרוזות)
    • subject (מחרוזת)
    • body (מחרוזת)

    צור מבנה EmailBuilder שמחזיק מצביע ל-Email שנבנה. ממש את NewEmailBuilder(), שמחזירה בנאי חדש עם Email מאותחל (פרוסות ריקות עבור to ו-cc).

    הוסף את מתודות הבנאי האלה, שכל אחת מהן מחזירה *EmailBuilder כדי לאפשר שרשור:

    • From(address string) - מגדירה את כתובת השולח
    • To(address string) - מוסיפה נמען לפרוסת to
    • CC(address string) - מוסיפה נמען לפרוסת cc
    • Subject(subject string) - מגדירה את שורת הנושא
    • Body(body string) - מגדירה את גוף הודעת הדוא״ל

    הוסף מתודת Build() שמחזירה את *Email שנבנה.

    לבסוף, הוסף למבנה Email מתודת Summary() שמחזירה מחרוזת בתבנית הזאת:

    From: [from]
    To: [comma-separated to addresses]
    CC: [comma-separated cc addresses or "none"]
    Subject: [subject]
    Body: [body]
  • main.go: בנה והצג הודעות דוא״ל באמצעות הבנאי.

    קרא את כתובת השולח, ואז קרא את מספר הנמענים ואת כתובת הדוא״ל של כל נמען. לאחר מכן, קרא את מספר הנמענים שמקבלים עותק (CC) ואת הכתובת של כל אחד מהם. לבסוף, קרא את הנושא ואת גוף ההודעה.

    השתמש ב-EmailBuilder עם שרשור מתודות כדי לבנות את הודעת הדוא״ל, ואז הדפס את הסיכום שלה.

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

  • שורה 1: כתובת השולח
  • שורה 2: מספר הנמענים
  • השורות הבאות: כתובת הדוא״ל של כל נמען
  • השורה הבאה: מספר הנמענים שמקבלים עותק (CC)
  • השורות הבאות: הכתובת של כל נמען שמקבל עותק (CC)
  • השורה הבאה: נושא
  • השורה האחרונה: גוף ההודעה

לדוגמה, בהינתן:

alice@company.com
2
bob@company.com
carol@company.com
1
manager@company.com
Weekly Report
Please find the weekly report attached.

הפלט שלך צריך להיות:

From: alice@company.com
To: bob@company.com, carol@company.com
CC: manager@company.com
Subject: Weekly Report
Body: Please find the weekly report attached.

ובהינתן:

support@service.com
1
customer@email.com
0
Your Ticket Update
Your support ticket has been resolved.

הפלט שלך צריך להיות:

From: support@service.com
To: customer@email.com
CC: none
Subject: Your Ticket Update
Body: Your support ticket has been resolved.

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

נסו בעצמכם

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// קרא את כתובת השולח
	from, _ := reader.ReadString('\n')
	from = strings.TrimSpace(from)

	// קרא את מספר הנמענים
	toCountStr, _ := reader.ReadString('\n')
	toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))

	// קרא את הכתובת של כל נמען
	toAddresses := make([]string, toCount)
	for i := 0; i < toCount; i++ {
		addr, _ := reader.ReadString('\n')
		toAddresses[i] = strings.TrimSpace(addr)
	}

	// קרא את מספר הנמענים בעותק (CC)
	ccCountStr, _ := reader.ReadString('\n')
	ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))

	// קרא כל כתובת בעותק (CC)
	ccAddresses := make([]string, ccCount)
	for i := 0; i < ccCount; i++ {
		addr, _ := reader.ReadString('\n')
		ccAddresses[i] = strings.TrimSpace(addr)
	}

	// קרא את הנושא
	subject, _ := reader.ReadString('\n')
	subject = strings.TrimSpace(subject)

	// קרא את גוף ההודעה
	body, _ := reader.ReadString('\n')
	body = strings.TrimSpace(body)

	// TODO: השתמש ב-EmailBuilder עם שרשור מתודות כדי לבנות את הודעת הדוא״ל
	// התחל עם NewEmailBuilder(), ואז שרשר את From(), To(), CC(), Subject(), Body()
	// לבסוף, קרא ל-Build() כדי לקבל את ה-Email

	// TODO: הדפס את סיכום הודעת הדוא״ל באמצעות המתודה Summary()
}
quiz iconבחנו את עצמכם

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

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

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