---
title: Паттерны
seo:
  title: Паттерны — Go Developer
  description: "Тема «Паттерны» для собеседования Go Developer. С какими паттернами проектирования знакомы? Расскажите про паттерны Builder (Строитель), Factory (Фабрика), Closer (Доводчик), Singleton (Одиночка)."
---

[Все темы Go Developer](/go-developer)

## <strong>С какими паттернами проектирования знакомы?</strong> [#q-14bee738d69b81d8bec1e56ca4c70bc7]

Основные паттерны проектирования&#58;

#### Порождающие паттерны&#58;

{/* prettier-ignore */}
1. <strong>Singleton (Одиночка)</strong>&#58;

    - Гарантирует, что у класса есть только один экземпляр и предоставляет к нему глобальную точку доступа.

1. <strong>Factory Method (Фабричный метод)</strong>&#58;

    - Определяет интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов.

1. <strong>Abstract Factory (Абстрактная фабрика)</strong>&#58;

    - Предоставляет интерфейс для создания семейств взаимосвязанных объектов, не специфицируя их конкретные классы.

1. <strong>Builder (Строитель)</strong>&#58;

    - Разделяет создание сложного объекта от его представления, позволяя строить объект пошагово.

1. <strong>Prototype (Прототип)</strong>&#58;

    - Создает объекты на основе существующего экземпляра через клонирование.

#### Структурные паттерны&#58;

{/* prettier-ignore */}
1. <code>Adapter</code> <strong>(Адаптер)</strong>&#58;

    - Позволяет объектам с несовместимыми интерфейсами работать вместе.

1. <code>Bridge</code> <strong>(Мост)</strong>&#58;

    - Разделяет абстракцию и её реализацию, чтобы они могли изменяться независимо.

1. <code>Composite</code> <strong>(Компоновщик)</strong>&#58;

    - Компонует объекты в древовидные структуры для представления иерархий часть-целое.

1. <code>Decorator</code> <strong>(Декоратор)</strong>&#58;

    - Добавляет новой функциональности объекту динамически.

1. <code>Facade</code> <strong>(Фасад)</strong>&#58;

    - Предоставляет унифицированный интерфейс к набору интерфейсов в подсистеме.

1. <code>Flyweight</code> <strong>(Приспособленец)</strong>&#58;

    - Позволяет вместить большее количество объектов, разделяя общий внутренний объект.

1. <code>Proxy</code> <strong>(Заместитель)</strong>&#58;

    - Предоставляет суррогатный объект, контролирующий доступ к другому объекту.

#### Поведенческие паттерны&#58;

{/* prettier-ignore */}
1. <code>Chain of Responsibility</code> <strong>(Цепочка обязанностей)</strong>&#58;

    - Передает запрос по цепочке обработчиков, пока один из них не обработает запрос.

1. <code>Command</code> <strong>(Команда)</strong>&#58;

    - Инкапсулирует запрос в виде объекта, позволяя параметризовать клиентами с различными запросами.

1. <code>Interpreter</code> <strong>(Интерпретатор)</strong>&#58;

    - Определяет грамматику языка и интерпретирует предложения этого языка.

1. <code>Iterator</code> <strong>(Итератор)</strong>&#58;

    - Предоставляет способ последовательного доступа ко всем элементам коллекции без раскрытия её внутреннего представления.

1. <code>Mediator</code> <strong>(Посредник)</strong>&#58;

    - Определяет объект, который инкапсулирует способ взаимодействия множества объектов.

1. <code>Memento</code> <strong>(Хранитель)</strong>&#58;

    - Сохраняет и восстанавливает внутреннее состояние объекта, не нарушая инкапсуляции.

1. <code>Observer</code> <strong>(Наблюдатель)</strong>&#58;

    - Определяет зависимость один ко многим между объектами, так что при изменении состояния одного объекта все зависимые уведомляются и обновляются.

1. <code>State</code> <strong>(Состояние)</strong>&#58;

    - Позволяет объекту изменять свое поведение при изменении его внутреннего состояния.

1. <code>Strategy</code> <strong>(Стратегия)</strong>&#58;

    - Определяет семейство алгоритмов, инкапсулирует их и делает их взаимозаменяемыми.

1. <code>Template Method</code> <strong>(Шаблонный метод)</strong>&#58;

    - Определяет скелет алгоритма в методе, оставляя определенные шаги подклассам.

1. <code>Visitor</code> <strong>(Посетитель)</strong>&#58;

    - Позволяет добавлять новые операции к объектам, не изменяя их классы.

:::note[Ссылки для изучения]

1. [Паттерны проектирования на Go](https://refactoring.guru/ru/design-patterns/go)
   :::

---

## <strong>Расскажите про паттерны</strong> <code>Builder</code> <strong>(Строитель),</strong> <code>Factory</code> <strong>(Фабрика),</strong> <code>Closer</code> <strong>(Доводчик),</strong> <code>Singleton</code> <strong>(Одиночка)</strong> [#q-14bee738d69b81f89577fc0399321dcf]

Примеры паттернов проектирования&#58;

#### <code>Builder</code> (Строитель)

<strong>Цель</strong>&#58; Разделить процесс создания сложного объекта от его
представления, позволяя создавать разные представления с помощью одного и того
же процесса построения.

<strong>Пример</strong>&#58;

- Используется для создания объектов с множеством опций или конфигураций.

- Включает в себя отдельный объект-строитель, который поэтапно собирает конечный объект.

<strong>Пример на Go</strong>&#58;

```go
type House struct {
    Windows string
    Doors   string
}

type HouseBuilder struct {
    house *House
}

func NewHouseBuilder() *HouseBuilder {
    return &HouseBuilder{house: &House{}}
}

func (b *HouseBuilder) SetWindows(windows string) *HouseBuilder {
    b.house.Windows = windows
    return b
}

func (b *HouseBuilder) SetDoors(doors string) *HouseBuilder {
    b.house.Doors = doors
    return b
}

func (b *HouseBuilder) Build() *House {
    return b.house
}

// Использование
builder := NewHouseBuilder()
house := builder.SetWindows("Wooden").SetDoors("Metal").Build()
```

#### <code>Factory</code> (Фабрика)

<strong>Цель</strong>&#58; Предоставить интерфейс для создания объектов, но
позволяет подклассам изменять тип создаваемых объектов.

<strong>Пример</strong>&#58;

- Позволяет создавать объекты без указания точного класса создаваемого объекта.

- Упрощает создание объектов и улучшает поддерживаемость кода.

<strong>Пример на Go</strong>&#58;

```go
type Animal interface {
    Speak() string
}

type Dog struct{}
func (d Dog) Speak() string { return "Woof" }

type Cat struct{}
func (c Cat) Speak() string { return "Meow" }

func AnimalFactory(animalType string) Animal {
    switch animalType {
    case "dog":
        return Dog{}
    case "cat":
        return Cat{}
    default:
        return nil
    }
}

// Использование
animal := AnimalFactory("dog")
fmt.Println(animal.Speak()) // Вывод: Woof
```

#### <code>Singleton</code> (Одиночка)

<strong>Цель</strong>&#58; Гарантировать, что у класса есть только один
экземпляр, и предоставить к нему глобальную точку доступа.

<strong>Пример</strong>&#58;

- Полезен, когда необходимо контролировать доступ к какому-либо ресурсу, например, к базе данных или к файлу конфигурации.

<strong>Пример на Go</strong>&#58;

```go
type singleton struct{}

var instance *singleton
var once sync.Once

func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

// Использование
s1 := GetInstance()
s2 := GetInstance()
fmt.Println(s1 == s2) // Вывод: true (оба указателя указывают на один экземпляр)
```

#### <code>Closer</code> (Доводчик)

<strong>Цель</strong>&#58; Упрощение управления ресурсами, которые должны быть
явно закрыты после использования (например, файлы, соединения).

<strong>Пример</strong>&#58;

- Часто используется для автоматического закрытия ресурсов в конце блока кода.

<strong>Пример на Go</strong>&#58;

```go
type Closer interface {
    Close() error
}

func UseResource(resource Closer) {
    defer resource.Close()
    // Работа с ресурсом
}

// Использование
file, err := os.Open("file.txt")
if err != nil {
    log.Fatal(err)
}
UseResource(file)
```

:::note[Ссылки для изучения]

1. [Паттерны проектирования на Go](https://refactoring.guru/ru/design-patterns/go)
   :::

---

## <strong>Расскажите, какой паттерн использовали в продукте/своем коде?</strong> [#q-14bee738d69b8133bd85c5187640d658]

Ниже — учебный пример однократной загрузки конфигурации. На собеседовании опишите собственную задачу и причины выбора паттерна; Singleton не обязателен для хранения конфигурации.

<strong>Решение</strong>&#58; Использование паттерна Singleton для управления
конфигурацией.

<strong>Код</strong>&#58;

```go
package config

import (
    "sync"
    "encoding/json"
    "os"
)

type Config struct {
    DatabaseURL string
    Port        int
}

var instance *Config
var once sync.Once
var loadErr error

func GetConfig() (*Config, error) {
    once.Do(func() {
        instance = &Config{}
        file, err := os.Open("config.json")
        if err != nil {
            loadErr = err
            return
        }
        defer file.Close()
        loadErr = json.NewDecoder(file).Decode(instance)
    })
    return instance, loadErr
}
```

<strong>Использование</strong>&#58;

```go
package main

import (
    "fmt"
    "myapp/config"
)

func main() {
    conf, err := config.GetConfig()
    if err != nil {
        fmt.Println("Cannot load config:", err)
        return
    }
    fmt.Println("Database URL:", conf.DatabaseURL)
    fmt.Println("Port:", conf.Port)
}
```

<strong>Преимущества</strong>&#58;

- <strong>Единая точка доступа</strong>&#58; Конфигурация загружается один раз и
  используется во всех частях приложения.

- sync.Once синхронизирует однократную загрузку, включая неуспешную попытку. Возвращаемую общую Config нельзя изменять конкурентно без дополнительной защиты; автоматического повтора загрузки здесь нет.

:::note[Ссылки для изучения]

1. [Паттерны проектирования на Go](https://refactoring.guru/ru/design-patterns/go)
   :::
