
-- ConcreteStrategies: plain functions
local function add_strategy(a, b)
return a + b
end
local function subtract_strategy(a, b)
return a - b
end
-- Context
local Calc = {}
Calc.__index = Calc
function Calc.new()
return setmetatable({}, Calc)
end
function Calc:execute(a, b)
if self.strategy == nil then
return 0
end
-- A dot, not a colon: the strategy is a plain
-- function in a field, it takes no self
return self.strategy(a, b)
end
local calc = Calc.new()
local result1 = calc:execute(5, 3)
-- result1 = 0
-- Setting the strategy is assigning the field
calc.strategy = add_strategy
local result2 = calc:execute(5, 3)
-- result2 = 8
calc.strategy = subtract_strategy
local result3 = calc:execute(5, 3)
-- result3 = 2
print("result1 = " .. result1)
print("result2 = " .. result2)
print("result3 = " .. result3)
Определяет семейство алгоритмов, инкапсулируя их и позволяя подставлять один вместо другого. Можно менять алгоритм независимо от клиента, который им пользуется.Read moreЗадача. Магазин считает стоимость доставки: по весу, по расстоянию или по фиксированной цене. Если один метод держит все способы в цепочке условий, он растёт с каждым новым способом. Правка одного способа может сломать другие, и ни один способ нельзя проверить отдельно. Идея. Каждый способ сделать работу становится отдельным объектом - стратегией. У всех стратегий одинаковый вид: те же входные данные и тот же тип результата. Объект, которому нужна эта работа, называют контекстом. Он хранит одну стратегию и вызывает её, не зная, какая именно ему досталась. Стратегию выбирает клиентский код и может заменить её в любой момент. Как читать пример. Каждая конкретная стратегия - это один алгоритм, и все они принимают одинаковые входные данные. Клиентский код выбирает стратегию. Код, который пользуется стратегией, только вызывает её и не знает, какую получил. В большинстве примеров одни и те же два числа дают другой результат после каждой смены стратегии. Большинство из них отвечают и на случай, когда стратегии нет. В некоторых языках стратегия - просто функция. Когда применять. Стратегия нужна, когда одну работу можно сделать несколькими способами, а выбор зависит от пользователя, данных или настроек. Для одного алгоритма, который не будет меняться, она ни к чему. Стратегия похожа на Состояние, но разница в том, кто делает выбор. Здесь алгоритм выбирает снаружи клиентский код, и стратегии ничего не знают друг о друге. В Состоянии объект сам переходит из состояния в состояние. Частая ошибка. Заставить контекст проверять, какая стратегия у него в руках. Условия возвращаются, и паттерн теряет смысл. Контекст должен только вызывать стратегию. |