 
                Стратегія на Go
Стратегія — це поведінковий патерн, який виносить набір алгоритмів у власні класи і робить їх взаємозамінними.
Інші об’єкти містять посилання на об’єкт-стратегію та делегують їй роботу. Програма може підмінити цей об’єкт іншим, якщо потрібен інший спосіб вирішення завдання.
Концептуальний приклад
Уявіть, що ви розробляєте «In-Memory-Cache». Оскільки він розташований всередині пам’яті, його розмір обмежений. Щойно він вщент заповниться, якісь записи доведеться прибрати, аби звільнити простір. Цю функцію можна реалізувати завдяки декільком алгоритмам, найпопулярніші серед них:
- Найбільш давно використовувалися (Least Recently Used — LRU): прибирає запис, який використовувався найбільш давно.
- «Першим прийшов, першим пішов» (First In, First Out — FIFO): прибирає запис, який був створений раніше за інші.
- Найменш часто використовувалися (Least Frequently Used — LFU): прибирає запис, який використовувався найменш часто.
Проблема полягає в тому, щоб відокремити кеш від цих алгоритмів для можливості їх заміни «на ходу». Крім цього, клас кешу мусить не змінюватися при додаванні нового алгоритму.
У такій ситуації нам допоможе патерн Стратегія. Він передбачає створення сімейства алгоритмів, кожен з яких має свій клас. Всі класи застосовують однаковий інтерфейс, що робить алгоритми взаємозамінними всередині цього сімейства. Назвемо цей загальний інтерфейс evictionAlgo.
Тепер основний клас нашого кеша включатиме у себе evictionAlgo. Замість прямої реалізації всіх типів алгоритмів витіснення всередині самого себе, наш клас передаватиме їх в evictionAlgo. Оскільки це інтерфейс, ми можемо безпосередньо під час виконання програми змінювати алгоритм на LRU, FIFO, LFU без змін у класі кеша.
evictionAlgo.go: Інтерфейс стратегії
package main
type EvictionAlgo interface {
	evict(c *Cache)
}
fifo.go: Конкретна стратегія
package main
import "fmt"
type Fifo struct {
}
func (l *Fifo) evict(c *Cache) {
	fmt.Println("Evicting by fifo strtegy")
}
lru.go: Конкретна стратегія
package main
import "fmt"
type Lru struct {
}
func (l *Lru) evict(c *Cache) {
	fmt.Println("Evicting by lru strtegy")
}
lfu.go: Конкретна стратегія
package main
import "fmt"
type Lfu struct {
}
func (l *Lfu) evict(c *Cache) {
	fmt.Println("Evicting by lfu strtegy")
}
cache.go: Контекст
package main
type Cache struct {
	storage      map[string]string
	evictionAlgo EvictionAlgo
	capacity     int
	maxCapacity  int
}
func initCache(e EvictionAlgo) *Cache {
	storage := make(map[string]string)
	return &Cache{
		storage:      storage,
		evictionAlgo: e,
		capacity:     0,
		maxCapacity:  2,
	}
}
func (c *Cache) setEvictionAlgo(e EvictionAlgo) {
	c.evictionAlgo = e
}
func (c *Cache) add(key, value string) {
	if c.capacity == c.maxCapacity {
		c.evict()
	}
	c.capacity++
	c.storage[key] = value
}
func (c *Cache) get(key string) {
	delete(c.storage, key)
}
func (c *Cache) evict() {
	c.evictionAlgo.evict(c)
	c.capacity--
}
main.go: Клієнтський код
package main
func main() {
	lfu := &Lfu{}
	cache := initCache(lfu)
	cache.add("a", "1")
	cache.add("b", "2")
	cache.add("c", "3")
	lru := &Lru{}
	cache.setEvictionAlgo(lru)
	cache.add("d", "4")
	fifo := &Fifo{}
	cache.setEvictionAlgo(fifo)
	cache.add("e", "5")
}
output.txt: Результат виконання
Evicting by lfu strtegy
Evicting by lru strtegy
Evicting by fifo strtegy