Menu
Coddy logo textTech

Pattern Builder in Go

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 80 di 107.

Il Builder Pattern separa la costruzione di un oggetto complesso dalla sua rappresentazione. A differenza del pattern Functional Options, il Builder usa una struct builder dedicata con metodi che configurano l’oggetto passo dopo passo.

Ecco come implementare un builder per una richiesta 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
}

Ogni metodo restituisce il puntatore al builder, consentendo di concatenare i metodi. Il metodo Build() finalizza e restituisce l'oggetto costruito:

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

Il pattern Builder è particolarmente adatto quando gli oggetti richiedono più passaggi di configurazione o quando vuoi imporre una sequenza di costruzione specifica. È particolarmente utile per creare oggetti immutabili o quando il processo di costruzione stesso deve essere convalidato.

challenge icon

Sfida

Facile

Creiamo un compositore di messaggi email usando il pattern Builder! I messaggi email hanno molti componenti opzionali, come destinatari, CC, oggetto, corpo e allegati, il che li rende perfetti per essere costruiti passo dopo passo concatenando i metodi.

Organizzerai il codice in due file:

  • email.go: definisci la struttura dell'email e il relativo builder.

    Crea una struct Email con questi campi:

    • from (string)
    • to (slice di stringhe)
    • cc (slice di stringhe)
    • subject (string)
    • body (string)

    Crea una struct EmailBuilder che contiene un puntatore a un'Email in fase di costruzione. Implementa NewEmailBuilder(), che restituisce un nuovo builder con un'Email inizializzata (slice vuote per to e cc).

    Aggiungi questi metodi del builder, ognuno dei quali restituisce *EmailBuilder per consentire la concatenazione:

    • From(address string) - imposta il mittente
    • To(address string) - aggiunge un destinatario alla slice to
    • CC(address string) - aggiunge un destinatario alla slice cc
    • Subject(subject string) - imposta l'oggetto
    • Body(body string) - imposta il corpo dell'email

    Aggiungi un metodo Build() che restituisce la *Email costruita.

    Infine, aggiungi un metodo Summary() su Email che restituisce una stringa in questo formato:

    From: [from]
    To: [comma-separated to addresses]
    CC: [comma-separated cc addresses or "none"]
    Subject: [subject]
    Body: [body]
  • main.go: crea e visualizza messaggi email usando il builder.

    Leggi l'indirizzo del mittente, poi leggi il numero di destinatari e l'indirizzo di ciascun destinatario. Poi, leggi il numero di destinatari in CC e ciascun indirizzo CC. Infine, leggi l'oggetto e il corpo.

    Usa EmailBuilder concatenando i metodi per costruire l'email, quindi stampa il riepilogo.

Verranno forniti i seguenti input:

  • Riga 1: indirizzo del mittente
  • Riga 2: numero di destinatari
  • Righe successive: indirizzo di ciascun destinatario
  • Riga successiva: numero di destinatari in CC
  • Righe successive: indirizzo di ciascun destinatario in CC
  • Riga successiva: oggetto
  • Riga finale: corpo

Ad esempio, dato:

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

L'output dovrebbe essere:

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.

E dato:

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

L'output dovrebbe essere:

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

Nota come il builder ti consenta di aggiungere più destinatari uno alla volta con chiamate ripetute a To() e come il pattern mantenga il processo di costruzione chiaro e leggibile anche in presenza di molti campi opzionali.

Provalo tu

package main

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

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

	// Leggi l'indirizzo del mittente
	from, _ := reader.ReadString('\n')
	from = strings.TrimSpace(from)

	// Leggi il numero di destinatari
	toCountStr, _ := reader.ReadString('\n')
	toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))

	// Leggi l'indirizzo di ogni destinatario
	toAddresses := make([]string, toCount)
	for i := 0; i < toCount; i++ {
		addr, _ := reader.ReadString('\n')
		toAddresses[i] = strings.TrimSpace(addr)
	}

	// Leggi il numero di destinatari CC
	ccCountStr, _ := reader.ReadString('\n')
	ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))

	// Leggi ogni indirizzo CC
	ccAddresses := make([]string, ccCount)
	for i := 0; i < ccCount; i++ {
		addr, _ := reader.ReadString('\n')
		ccAddresses[i] = strings.TrimSpace(addr)
	}

	// Leggi l'oggetto
	subject, _ := reader.ReadString('\n')
	subject = strings.TrimSpace(subject)

	// Leggi il corpo del messaggio
	body, _ := reader.ReadString('\n')
	body = strings.TrimSpace(body)

	// TODO: Usa EmailBuilder con chiamate ai metodi concatenate per costruire l'email
	// Inizia con NewEmailBuilder(), poi concatena From(), To(), CC(), Subject(), Body()
	// Infine chiama Build() per ottenere l'Email

	// TODO: Stampa il riepilogo dell'email usando il metodo Summary()
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online