Создание сложных объектов может быть громоздким и трудным в управлении, особенно когда задействовано несколько конфигураций и комбинаций компонентов. Шаблон Builder — это шаблон проектирования, который упрощает процесс создания сложных объектов, позволяя создавать их шаг за шагом. Это приводит к более читабельному, поддерживаемому и гибкому коду.
В этом посте мы углубимся в паттерн Builder и продемонстрируем его практическое применение на примере, реализованном в Go. Мы создадим объект Product
из нескольких частей, демонстрируя способность шаблона Builder облегчить создание сложных объектов, сохраняя при этом гибкость для легкого создания различных конфигураций.
Перейти к реализации шаблона Builder
На протяжении всего поста мы представим реализацию шаблона Builder на Go и объясним ключевые задействованные компоненты, такие как Product
, Builder
и ConcreteBuilder
. Мы также обсудим их соответствующие роли в процессе строительства. Приведенный пример иллюстрирует, как шаблон Builder можно использовать для пошагового создания сложных объектов, что позволяет легко настраивать различные варианты объектов.
Устранение утечки конфигурации между сборками
В этом посте мы также рассмотрим распространенную ловушку в реализациях шаблонов Builder, а именно потенциальную утечку конфигураций между разными сборками. Мы продемонстрируем, как правильно сбрасывать внутреннее состояние компоновщика после каждой сборки, чтобы убедиться, что конфигурации изолированы и не влияют на последующие сборки.
package main import "fmt" // Product represents the complex object to be built. type Product struct { partA string partB string partC string } func (p *Product) String() string { return fmt.Sprintf("Product{partA: %s, partB: %s, partC: %s}", p.partA, p.partB, p.partC) } // Builder is the interface for building a complex object step by step. type Builder interface { SetPartA(string) Builder SetPartB(string) Builder SetPartC(string) Builder Build() *Product } // ConcreteBuilder is the concrete implementation of the Builder interface. type ConcreteBuilder struct { product Product } func (cb *ConcreteBuilder) SetPartA(value string) Builder { cb.product.partA = value return cb } func (cb *ConcreteBuilder) SetPartB(value string) Builder { cb.product.partB = value return cb } func (cb *ConcreteBuilder) SetPartC(value string) Builder { cb.product.partC = value return cb } func (cb *ConcreteBuilder) Build() *Product { product := cb.product cb.reset() return &product } // reset resets the builder's internal product state. func (cb *ConcreteBuilder) reset() { cb.product = Product{} } func main() { builder := &ConcreteBuilder{} // Building a product using the builder product1 := builder.SetPartA("Custom part A").SetPartB("Custom part B").SetPartC("Custom part C").Build() fmt.Println("Product 1:", product1) // Building another product with different configuration product2 := builder.SetPartA("Another part A").SetPartB("Another part B").Build() fmt.Println("Product 2:", product2) }
В этом примере у нас есть три основных компонента:
Product
: Строящийся сложный объект. В данном случае он состоит из трех частей (partA
,partB
иpartC
).Builder
: Интерфейс для пошагового построения сложного объекта. В нем есть методы настройки каждой части (SetPartA
,SetPartB
иSetPartC
) и метод построения конечного продукта (Build
).ConcreteBuilder
: конкретная реализация интерфейсаBuilder
. Он реализует каждый метод установки деталей и метод сборки конечного продукта. Метод internalreset
сбрасывает внутреннее состояние продукта компоновщика на новый пустой объектProduct
. Мы вызываем методreset
внутри методаBuild
перед возвратом сконструированного продукта. Это гарантирует, что конфигурация одного продукта не повлияет на конфигурацию следующего продукта, созданного с использованием того же компоновщика.
В функции main
мы создаем ConcreteBuilder
, строим Product
с помощью компоновщика и печатаем полученный продукт. В этом примере показано, как шаблон Builder можно использовать для пошагового создания сложных объектов, что позволяет использовать различные конфигурации и более читаемый и удобный код.
Заключение
Поняв шаблон Builder и его реализацию на Go, вы будете хорошо подготовлены для применения шаблона в своих собственных проектах, тем самым упрощая процессы создания сложных объектов и повышая удобочитаемость и удобство сопровождения вашего кода.
Если вам нравится читать статьи на Medium и вы заинтересованы в том, чтобы стать участником, я буду рад поделиться с вами своей реферальной ссылкой!