Найти в Дзене
Skill Up In IT

Golang паттерны

Паттерны проектирования — это проверенные временем решения распространенных проблем в разработке программного обеспечения. Они помогают создавать гибкий, поддерживаемый и масштабируемый код. GoLang, несмотря на свою простоту и минималистичный синтаксис, отлично подходит для реализации многих паттернов проектирования. В этой статье мы рассмотрим основные паттерны и их реализацию на Go. Синглтон — это паттерн, который гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру. В GoLang синглтон можно реализовать с использованием пакетов и функций sync.Once. go: package main import ( "fmt" "sync" ) type Singleton struct { data string } var ( instance *Singleton once sync.Once ) func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{data: "Это единственный экземпляр"} }) return instance } func main() { s1 := GetInstance() s2 := GetInstance() fmt.Println(s1 == s2) // true fmt.Println(s1.data)
Оглавление

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

Синглтон (Singleton)

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

В GoLang синглтон можно реализовать с использованием пакетов и функций sync.Once.

go:

package main
import (
"fmt"
"sync"
)
type Singleton struct {
data string
}
var (
instance *Singleton
once sync.Once
)
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{data: "Это единственный экземпляр"}
})
return instance
}
func main() {
s1 := GetInstance()
s2 := GetInstance()
fmt.Println(s1 == s2) // true
fmt.Println(s1.data) // Это единственный экземпляр
}

Фабрика (Factory)

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

go:

package main
import "fmt"
type Product interface {
Use() string
}
type ConcreteProductA struct{}
func (p *ConcreteProductA) Use() string {
return "Используется продукт A"
}
type ConcreteProductB struct{}
func (p *ConcreteProductB) Use() string {
return "Используется продукт B"
}
type Factory struct{}
func (f *Factory) CreateProduct(productType string) Product {
switch productType {
case "A":
return &ConcreteProductA{}
case "B":
return &ConcreteProductB{}
default:
return nil
}
}
func main() {
factory := &Factory{}
productA := factory.CreateProduct("A")
fmt.Println(productA.Use()) // Используется продукт A
productB := factory.CreateProduct("B")
fmt.Println(productB.Use()) // Используется продукт B
}

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

Стратегия — это паттерн, который позволяет выбирать алгоритм во время выполнения программы. Он определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.

go:

package main
import "fmt"
type Strategy interface {
Execute(a, b int) int
}
type AddStrategy struct{}
func (s *AddStrategy) Execute(a, b int) int {
return a + b
}
type SubtractStrategy struct{}
func (s *SubtractStrategy) Execute(a, b int) int {
return a - b
}
type Context struct {
strategy Strategy
}
func (c *Context) SetStrategy(strategy Strategy) {
c.strategy = strategy
}
func (c *Context) ExecuteStrategy(a, b int) int {
return c.strategy.Execute(a, b)
}
func main() {
context := &Context{}
context.SetStrategy(&AddStrategy{})
fmt.Println(context.ExecuteStrategy(5, 3)) // 8
context.SetStrategy(&SubtractStrategy{})
fmt.Println(context.ExecuteStrategy(5, 3)) // 2
}

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

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

go:

package main
import "fmt"
type Observer interface {
Update(message string)
}
type Subject struct {
observers []Observer
}
func (s *Subject) Attach(observer Observer) {
s.observers = append(s.observers, observer)
}
func (s *Subject) Notify(message string) {
for _, observer := range s.observers {
observer.Update(message)
}
}
type ConcreteObserver struct {
name string
}
func (o *ConcreteObserver) Update(message string) {
fmt.Printf("%s получил сообщение: %s\n", o.name, message)
}
func main() {
subject := &Subject{}
observer1 := &ConcreteObserver{name: "Наблюдатель 1"}
observer2 := &ConcreteObserver{name: "Наблюдатель 2"}
subject.Attach(observer1)
subject.Attach(observer2)
subject.Notify("Привет, мир!")
}

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

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

go:

package main
import "fmt"
type Component interface {
Operation() string
}
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() string {
return "Базовая операция"
}
type Decorator struct {
component Component
}
func (d *Decorator) Operation() string {
return "Декорированная " + d.component.Operation()
}
func main() {
component := &ConcreteComponent{}
decoratedComponent := &Decorator{component: component}
fmt.Println(component.Operation()) // Базовая операция
fmt.Println(decoratedComponent.Operation()) // Декорированная Базовая операция
}

Адаптер (Adapter)

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

go:

package main
import "fmt"
type OldSystem struct{}
func (o *OldSystem) LegacyOperation() string {
return "Старая система"
}
type NewSystem interface {
NewOperation() string
}
type Adapter struct {
oldSystem *OldSystem
}
func (a *Adapter) NewOperation() string {
return "Адаптированная " + a.oldSystem.LegacyOperation()
}
func main() {
oldSystem := &OldSystem{}
adapter := &Adapter{oldSystem: oldSystem}
fmt.Println(adapter.NewOperation()) // Адаптированная Старая система
}

Заключение

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