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

Паттерн Strategy относится к поведенческим паттернам уровня объекта.
Паттерн Strategy определяет набор алгоритмов схожих по роду деятельности, инкапсулирует их в отдельный класс и делает их подменяемыми. Паттерн Strategy позволяет подменять алгоритмы без участия клиентов, которые используют эти алгоритмы.
Требуется для реализации:
Класс Context, представляющий собой контекст выполнения той или иной стратегии;
Абстрактный класс Strategy, определяющий интерфейс различных стратегий;
Класс ConcreteStrategyA, реализует одну из стратегий представляющую собой алгоритмы, направленные на достижение определенной цели;
Класс ConcreteStrategyB, реализует одно из стратегий представляющую собой алгоритмы, направленные на достижение определенной цели.
[!] В описании паттерна применяются общие понятия, такие как Класс, Объект, Абстрактный класс. Применимо к языку Go, это Пользовательский Тип, Значение этого Типа и Интерфейс. Также в языке Go за место общепринятого наследования используется агрегирование и встраивание.
//strategy.go
// Package strategy is an example of the Strategy Pattern.
package strategy
// StrategySort provides an interface for sort algorithms.
type StrategySort interface {
	Sort([]int)
}
// BubbleSort implements bubble sort algorithm.
type BubbleSort struct {
}
// Sort sorts data.
func (s *BubbleSort) Sort(a []int) {
	size := len(a)
	if size < 2 {
		return
	}
	for i := 0; i < size; i++ {
		for j := size - 1; j >= i+1; j-- {
			if a[j] < a[j-1] {
				a[j], a[j-1] = a[j-1], a[j]
			}
		}
	}
}
// InsertionSort implements insertion sort algorithm.
type InsertionSort struct {
}
// Sort sorts data.
func (s *InsertionSort) Sort(a []int) {
	size := len(a)
	if size < 2 {
		return
	}
	for i := 1; i < size; i++ {
		var j int
		var buff = a[i]
		for j = i - 1; j >= 0; j-- {
			if a[j] < buff {
				break
			}
			a[j+1] = a[j]
		}
		a[j+1] = buff
	}
}
// Context provides a context for execution of a strategy.
type Context struct {
	strategy StrategySort
}
// Algorithm replaces strategies.
func (c *Context) Algorithm(a StrategySort) {
	c.strategy = a
}
// Sort sorts data according to the chosen strategy.
func (c *Context) Sort(s []int) {
	c.strategy.Sort(s)
}
//strategy_test.go
package strategy
import (
	"strconv"
	"testing"
)
func TestStrategy(t *testing.T) {
	data1 := []int{8, 2, 6, 7, 1, 3, 9, 5, 4}
	data2 := []int{8, 2, 6, 7, 1, 3, 9, 5, 4}
	ctx := new(Context)
	ctx.Algorithm(&BubbleSort{})
	ctx.Sort(data1)
	ctx.Algorithm(&InsertionSort{})
	ctx.Sort(data2)
	expect := "1,2,3,4,5,6,7,8,9,"
	var result1 string
	for _, val := range data1 {
		result1 += strconv.Itoa(val) + ","
	}
	if result1 != expect {
		t.Errorf("Expect result1 to equal %s, but %s.\n", expect, result1)
	}
	var result2 string
	for _, val := range data2 {
		result2 += strconv.Itoa(val) + ","
	}
	if result2 != expect {
		t.Errorf("Expect result2 to equal %s, but %s.\n", expect, result2)
	}
}