← Назад к вопросам

Приведи пример паттернов, которые закрываются интерфейсами

2.3 Middle🔥 181 комментариев
#Микросервисы и архитектура#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры паттернов, которые закрываются интерфейсами в Go

В Go интерфейсы играют ключевую роль в реализации многих классических паттернов проектирования, обеспечивая абстракцию и полиморфизм без явного наследования. «Закрываться интерфейсами» означает, что паттерн реализуется через интерфейсы, которые определяют контракты для взаимодействия компонентов, что делает систему гибкой и расширяемой.

Стратегия (Strategy Pattern)

Паттерн Стратегия позволяет заменять алгоритмы или поведение объектов динамически через интерфейсы. Интерфейс определяет метод, который различные стратегии реализуют.

// Интерфейс стратегии
type PaymentStrategy interface {
    Pay(amount float64) error
}

// Конкретные стратегии
type CreditCardPayment struct {
    CardNumber string
}

func (c *CreditCardPayment) Pay(amount float64) error {
    fmt.Printf("Оплата %.2f с карты %s\n", amount, c.CardNumber)
    return nil
}

type PayPalPayment struct {
    Email string
}

func (p *PayPalPayment) Pay(amount float64) error {
    fmt.Printf("Оплата %.2f через PayPal %s\n", amount, p.Email)
    return nil
}

// Контекст, использующий стратегию
type ShoppingCart struct {
    paymentStrategy PaymentStrategy
}

func (cart *ShoppingCart) SetPaymentStrategy(strategy PaymentStrategy) {
    cart.paymentStrategy = strategy
}

func (cart *ShoppingCart) Checkout(amount float64) error {
    return cart.paymentStrategy.Pay(amount)
}

Итератор (Iterator Pattern)

Паттерн Итератор предоставляет способ последовательного доступа к элементам коллекции без раскрытия её внутренней структуры. Интерфейсы Iterator и Iterable стандартизируют этот процесс.

// Интерфейс итератора
type Iterator interface {
    Next() interface{}
    HasNext() bool
}

// Интерфейс для коллекции
type Iterable interface {
    Iterator() Iterator
}

// Реализация для списка
type ListIterator struct {
    list []interface{}
    index int
}

func (li *ListIterator) Next() interface{} {
    val := li.list[li.index]
    li.index++
    return val
}

func (li *ListIterator) HasNext() bool {
    return li.index < len(li.list)
}

type MyList struct {
    items []interface{}
}

func (ml *MyList) Iterator() Iterator {
    return &ListIterator{list: ml.items, index: 0}
}

Фабричный метод (Factory Method Pattern)

Паттерн Фабричный метод определяет интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов. В Go это часто реализуется через интерфейс фабрики и интерфейс продукта.

// Интерфейс продукта
type Document interface {
    Open()
    Save()
}

// Интерфейс фабрики
type DocumentFactory interface {
    CreateDocument() Document
}

// Конкретные реализации
type PDFDocument struct{}

func (pdf *PDFDocument) Open() { fmt.Println("Открыт PDF документ") }
func (pdf *PDFDocument) Save() { fmt.Println("PDF документ сохранен") }

type PDFFactory struct{}

func (pf *PDFFactory) CreateDocument() Document {
    return &PDFDocument{}
}

// Использование
func CreateAndUseDocument(factory DocumentFactory) {
    doc := factory.CreateDocument()
    doc.Open()
    doc.Save()
}

Наблюдатель (Observer Pattern)

Паттерн Наблюдатель позволяет объектам подписываться на события других объектов. Интерфейсы Subject и Observer формализуют эту связь.

// Интерфейс наблюдателя
type Observer interface {
    Update(data interface{})
}

// Интерфейс субъекта
type Subject interface {
    RegisterObserver(o Observer)
    RemoveObserver(o Observer)
    NotifyObservers()
}

// Конкретный субъект
type NewsPublisher struct {
    observers []Observer
    news      string
}

func (np *NewsPublisher) RegisterObserver(o Observer) {
    np.observers = append(np.observers, o)
}

func (np *NewsPublisher) RemoveObserver(o Observer) {
    // Удаление наблюдателя из списка
}

func (np *NewsPublisher) NotifyObservers() {
    for _, observer := range np.observers {
        observer.Update(np.news)
    }
}

func (np *NewsPublisher) SetNews(news string) {
    np.news = news
    np.NotifyObservers()
}

Декоратор (Decorator Pattern)

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

// Интерфейс компонента
type Coffee interface {
    Cost() float64
    Description() string
}

// Базовый компонент
type SimpleCoffee struct{}

func (sc *SimpleCoffee) Cost() float64 { return 2.0 }
func (sc *SimpleCoffee) Description() string { return "Простой кофе" }

// Декоратор
type MilkDecorator struct {
    coffee Coffee
}

func (md *MilkDecorator) Cost() float64 {
    return md.coffee.Cost() + 0.5
}

func (md *MilkDecorator) Description() string {
    return md.coffee.Description() + ", с молоком"
}

Адаптер (Adapter Pattern)

Паттерн Адаптер преобразует интерфейс одного класса в интерфейс другого через промежуточный интерфейс адаптера.

// Целевой интерфейс
type ModernPrinter interface {
    PrintStructured(data string)
}

// Старый класс с несовместимым интерфейсом
type LegacyPrinter struct{}

func (lp *LegacyPrinter) Print(data string) {
    fmt.Println("Legacy: " + data)
}

// Адаптер
type LegacyAdapter struct {
    legacy *LegacyPrinter
}

func (la *LegacyAdapter) PrintStructured(data string) {
    la.legacy.Print("Adapter: " + data)
}

Заключение

Интерфейсы в Go являются мощным инструментом для реализации паттернов проектирования, поскольку они:

  • Определяют четкие контракты между компонентами.
  • Позволяют достигать полиморфизма без жестких связей.
  • Обеспечивают тестируемость через возможность подмены реализаций.
  • Способствуют модульности и соблюдению принципа Dependency Inversion.

Использование интерфейсов в паттернах делает код более гибким, расширяемым и соответствует философии Go — простота через абстракцию, где интерфейсы служат ключевым механизмом для достижения этой простоты.

Приведи пример паттернов, которые закрываются интерфейсами | PrepBro