Menu
Coddy logo textTech

Wzorzec Builder w Go

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 80 z 107.

Wzorzec Builder oddziela tworzenie złożonego obiektu od jego reprezentacji. W przeciwieństwie do wzorca Functional Options, Builder wykorzystuje dedykowaną strukturę konstruktora z metodami, które konfigurują obiekt krok po kroku.

Oto, jak zaimplementować budowniczego żądania 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
}

Każda metoda zwraca wskaźnik do obiektu buildera, umożliwiając łączenie metod. Metoda Build() finalizuje i zwraca skonstruowany obiekt:

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

Wzorzec Builder sprawdza się doskonale, gdy obiekty wymagają wielu kroków konfiguracji lub gdy chcesz wymusić określoną kolejność tworzenia. Jest szczególnie przydatny przy tworzeniu niezmiennych obiektów lub gdy sam proces tworzenia wymaga walidacji.

challenge icon

Wyzwanie

Łatwy

Zbudujmy kompozytor wiadomości e-mail z użyciem wzorca Builder! Wiadomości e-mail mają wiele opcjonalnych elementów: odbiorców, DW, temat, treść i załączniki, dzięki czemu doskonale nadają się do konstruowania krok po kroku z łańcuchowym wywoływaniem metod.

Uporządkujesz swój kod w dwóch plikach:

  • email.go: Zdefiniuj strukturę wiadomości e-mail i jej builder.

    Utwórz strukturę Email z następującymi polami:

    • from (string)
    • to (wycinek ciągów znaków)
    • cc (wycinek ciągów znaków)
    • subject (string)
    • body (string)

    Utwórz strukturę EmailBuilder, która przechowuje wskaźnik do konstruowanego obiektu Email. Zaimplementuj NewEmailBuilder(), która zwraca nowy builder z zainicjowanym obiektem Email (puste wycinki dla to i cc).

    Dodaj następujące metody buildera, z których każda zwraca *EmailBuilder, aby umożliwić łańcuchowe wywoływanie:

    • From(address string) — ustawia adres nadawcy
    • To(address string) — dodaje odbiorcę do wycinka to
    • CC(address string) — dodaje odbiorcę do wycinka cc
    • Subject(subject string) — ustawia temat
    • Body(body string) — ustawia treść wiadomości e-mail

    Dodaj metodę Build(), która zwraca skonstruowany obiekt *Email.

    Na koniec dodaj metodę Summary() do Email, która zwraca ciąg znaków w następującym formacie:

    From: [from]
    To: [comma-separated to addresses]
    CC: [comma-separated cc addresses or "none"]
    Subject: [subject]
    Body: [body]
  • main.go: Twórz i wyświetlaj wiadomości e-mail za pomocą buildera.

    Odczytaj adres nadawcy, a następnie liczbę odbiorców i adres każdego z nich. Następnie odczytaj liczbę odbiorców DW i adres każdego z nich. Na koniec odczytaj temat i treść wiadomości.

    Użyj EmailBuildera z łańcuchowym wywoływaniem metod, aby skonstruować wiadomość e-mail, a następnie wyświetl jej podsumowanie.

Dane wejściowe będą miały następującą postać:

  • Wiersz 1: Adres nadawcy
  • Wiersz 2: Liczba odbiorców
  • Kolejne wiersze: Adres każdego odbiorcy
  • Następny wiersz: Liczba odbiorców DW
  • Kolejne wiersze: Adres każdego odbiorcy DW
  • Następny wiersz: Temat
  • Ostatni wiersz: Treść wiadomości

Na przykład dla danych:

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

Wynik powinien być następujący:

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.

A dla danych:

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

Wynik powinien być następujący:

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

Zwróć uwagę, że builder pozwala dodawać wielu odbiorców pojedynczo za pomocą kolejnych wywołań To(), a wzorzec sprawia, że proces konstruowania pozostaje przejrzysty i czytelny nawet przy wielu opcjonalnych polach.

Spróbuj swoich sił

package main

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

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

	// Odczytaj adres nadawcy
	from, _ := reader.ReadString('\n')
	from = strings.TrimSpace(from)

	// Odczytaj liczbę odbiorców
	toCountStr, _ := reader.ReadString('\n')
	toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))

	// Odczytaj adres każdego odbiorcy
	toAddresses := make([]string, toCount)
	for i := 0; i < toCount; i++ {
		addr, _ := reader.ReadString('\n')
		toAddresses[i] = strings.TrimSpace(addr)
	}

	// Odczytaj liczbę odbiorców CC
	ccCountStr, _ := reader.ReadString('\n')
	ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))

	// Odczytaj każdy adres CC
	ccAddresses := make([]string, ccCount)
	for i := 0; i < ccCount; i++ {
		addr, _ := reader.ReadString('\n')
		ccAddresses[i] = strings.TrimSpace(addr)
	}

	// Odczytaj temat
	subject, _ := reader.ReadString('\n')
	subject = strings.TrimSpace(subject)

	// Odczytaj treść
	body, _ := reader.ReadString('\n')
	body = strings.TrimSpace(body)

	// TODO: Użyj EmailBuilder z łańcuchowym wywoływaniem metod, aby utworzyć wiadomość e-mail
	// Zacznij od NewEmailBuilder(), a następnie wywołaj łańcuchowo From(), To(), CC(), Subject(), Body()
	// Na koniec wywołaj Build(), aby uzyskać Email

	// TODO: Wypisz podsumowanie wiadomości e-mail za pomocą metody Summary()
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online