
В этом видео мы разберем такой паттерн, как Stategy, или по русски Стратегия. Он заключается в том, что у нас есть какая-то базовая сущность и мы хотим организовать код так, чтобы мы могли добавлять реализацию каких-то внутренних методов с помощью дополнительных сущностей.
Один из примеров - это авторизация, которая обладает базовым функционалом и, которую мы можем с помощью дополнительный модулей расширять, делая, например, авторизацию по логину и паролю, либо по токену, либо через oath и так далее. Но главная идея в том, чтобы мы могли добавлять неограниченое количество модулей без изменения кода базовой сущности. Именно так работает passport.js в node.
Но давайте с вами сейчас попробуем этот паттерн на простом примере.
Мы хотим написать логгер, который в результате будет работать вот так.
logger(
logToConsoleStrategy,
'log',
'log first message to console'
)
То есть мы передали в logger logToConsoleStrategy, которая будет реализовывать вывод в консоль, уровень лога: (log, error, warn) и сообщение.
Давайте реализуем этот код.
const logger = (strategy, level, message) => {
return strategy(level, message)
}
const logToConsoleStrategy = (level, message) => console[level](message)
logger(
logToConsoleStrategy,
'log',
'log first message to console'
)
Мы создали logger, который не содержит в себе никакого кода, но вызывает переданую стратегию с правильными аргументами.
И отдельно мы реализовали стратегию, которая может делать все, что угодно, но обязана быть функцией и иметь аргументы level и message.
Если мы посмотрим в браузер, то у нас вывелось сообщение к консоль.
Идея в том, что мы можем в любой момент заменить logToConsoleStrategy на любую другую стратегию и все будет по прежнему работать. Например, мы можем выводить ошибки на экран или отправлять в какой-то сервис ошибок с помощью fetch.
Давайте добавим стратегию вывода в DOM.
const logToDOMStrategy = (level, message, node) => {
node.innerHTML = `<div class='${level}'>${message}</div>`
}
logger(
logToDOMStrategy,
'warn',
'log second message to dom',
document.querySelector('#log')
)
Мы добавили еще одну стратегию, но у нас появился дополнительный параметр node, потому что нам нужно знать, в какой елемент выводить сообщение. Поэтому нам нужно модифицировать наш logger, чтобы передавать в стратегию любые дополнительные данные.
const logger = (strategy, level, message, ...args) => {
return strategy(level, message, ...args)
}
И мы должны добавить элемент log в нашу разметку.
<div id='log'></div>
Если мы посмотрим в браузер, то у нас вывелось наше сообщение в DOM элемент и мы можем добавить стили для класса .warn.
<style>
.warn {
color: orange
}
</style>
Таким образом мы можем легко добавлять новые стратегии не модифицируя на logger.
Паттерн стратегия позволяет легко масштабировать код добавляя стратегии и не изменяя базовую логику.
Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.