Sobes.tech
Middle

Opowiedz o wzorcu projektowym Builder (Budowniczy).

sobes.tech AI

Odpowiedź od AI

Builder to wzorzec kreacyjny, który umożliwia stopniowe tworzenie złożonych obiektów.

Stosuje się go, gdy:

  • Proces tworzenia obiektu jest skomplikowany i obejmuje wiele kroków.
  • Konieczne jest tworzenie różnych reprezentacji tego samego obiektu.
  • Konstruktor obiektu ma dużą liczbę parametrów opcjonalnych.

Wzorzec składa się z następujących ról:

  • Builder: Interfejs definiujący kroki budowy obiektu.
  • ConcreteBuilder: Konkretna implementacja Buildera, wykonująca kroki budowy i udostępniająca metodę uzyskania gotowego obiektu.
  • Product: Złożony obiekt, który jest budowany.
  • Director (opcjonalnie): Określa kolejność wywołań kroków budowy.

Przykład implementacji w Golang bez Director:

// Product - obiekt, który budujemy
type Pizza struct {
	Dough   string
	Sauce   string
	Toppings []string
}

// Builder - interfejs budowniczego
type PizzaBuilder interface {
	SetDough(dough string) PizzaBuilder
	SetSauce(sauce string) PizzaBuilder
	AddTopping(topping string) PizzaBuilder
	Build() Pizza // Metoda uzyskania gotowego obiektu
}

// ConcreteBuilder - konkretna implementacja budowniczego
type HawaiianPizzaBuilder struct {
	pizza Pizza
}

func NewHawaiianPizzaBuilder() *HawaiianPizzaBuilder {
	return &HawaiianPizzaBuilder{}
}

func (b *HawaiianPizzaBuilder) SetDough(dough string) PizzaBuilder {
	b.pizza.Dough = dough
	return b
}

func (b *HawaiianPizzaBuilder) SetSauce(sauce string) PizzaBuilder {
	b.pizza.Sauce = sauce
	return b
}

func (b *HawaiianPizzaBuilder) AddTopping(topping string) PizzaBuilder {
	b.pizza.Toppings = append(b.pizza.Toppings, topping)
	return b
}

func (b *HawaiianPizzaBuilder) Build() Pizza {
	return b.pizza
}

// Przykład użycia
func main() {
	// Tworzymy buildera dla hawajskiej pizzy
	builder := NewHawaiianPizzaBuilder()

	// Budujemy pizzę krok po kroku
	pizza := builder.
		SetDough("cienkie").
		SetSauce("pomidor").
		AddTopping("ananas").
		AddTopping("szynka").
		Build() // Otrzymujemy gotową pizzę

	fmt.Printf("Utworzona pizza: %+v\n", pizza)
}

Zalety wzorca:

  • Pozwala odseparować proces budowy złożonego obiektu od jego reprezentacji.
  • Umożliwia tworzenie obiektu krok po kroku.
  • Ułatwia tworzenie różnych reprezentacji tego samego obiektu.
  • Sprawia, że kod tworzenia obiektu jest bardziej czytelny i łatwiejszy w utrzymaniu przy dużej liczbie parametrów.

Wady wzorca:

  • Zwiększa liczbę klas w projekcie.
  • Może być nadmierny dla prostych obiektów.