Шаблон Builder
Сегодня я хочу углубиться в шаблон Builder — важную концепцию дизайна, с которой многие разработчики сталкиваются на определенном этапе своей карьеры. Этот шаблон значительно расширяет наши возможности создавать сложные объекты контролируемым и масштабируемым образом. Однако всегда есть куда совершенствоваться, особенно в том, как мы управляем процессом строительства.
Понимание шаблона Builder
Шаблон Builder упрощает создание сложных объектов, разбивая процесс строительства на отдельные, управляемые этапы, выполняемые директором и строителем. Директор контролирует порядок этапов строительства, а разные строители реализуют конкретные детали возводимого объекта. Вот базовый пример, использующий аналогию со строительством дома:
package main
type Director struct {
builder IHouseBuilder
}
func newDirector(b IHouseBuilder) *Director {
return &Director{
builder: b,
}
}
func (d *Director) setBuilder(b IHouseBuilder) {
d.builder = b
}
func (d *Director) buildHouse() House {
d.builder.setDoors()
d.builder.setWindows()
d.builder.setRooms()
return d.builder.getHouse()
}
В этом фрагменте перед Director
стоит задача построить дом, последовательно инициируя строительство дверей, окон и комнат. Такой пошаговый подход гарантирует, что каждый компонент будет завершен до начала следующего, что традиционно занимает около 3 секунд для нашей гипотетической сборки.
Оптимизация с параллелизмом
Что если бы мы могли ускорить этот процесс? Вместо последовательного создания каждого компонента мы могли бы использовать параллелизм для одновременного выполнения этих задач, что значительно сократило бы время сборки.
package main
import "golang.org/x/sync/errgroup"
type Director struct {
builder IHouseBuilder
}
func newDirector(b IHouseBuilder) *Director {
return &Director{
builder: b,
}
}
func (d *Director) setBuilder(b IHouseBuilder) {
d.builder = b
}
func (d *Director) buildHouse() (House, error) {
var eg errgroup.Group
eg.Go(d.builder.setDoors)
eg.Go(d.builder.setWindows)
eg.Go(d.builder.setRooms)
if err := eg.Wait(); err != nil {
return House{}, err
}
return d.builder.getHouse(), nil
}
Используя пакет Go errgroup
, мы можем распараллелить этапы построения. Это изменение позволяет строить двери, окна и комнаты одновременно, потенциально сокращая общее время сборки примерно до 1 секунды — значительное улучшение!
Влияние параллелизма
Реализация параллелизма в шаблоне Builder может значительно повысить эффективность, особенно в таких языках, как Go, которые разработаны с учетом параллелизма. Этот метод гарантирует, что конечный результат останется неизменным, одновременно оптимизируя процесс строительства.
Ресурсы и дальнейшее исследование
Если вы хотите поэкспериментировать с этими концепциями, вы можете получить доступ к полным примерам кода здесь: