Приведи пример паттернов, которые закрываются интерфейсами
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Примеры паттернов, которые закрываются интерфейсами в 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 — простота через абстракцию, где интерфейсы служат ключевым механизмом для достижения этой простоты.