Что такое паттерн, или Почему иногда так сложно вести себя «прилично»?
Поведенческий паттерн — это набор сценариев «по умолчанию», которые человек может проигрывать на автопилоте. Это может быть сценарий «приличного поведения» при знакомстве с деловыми партнерами или, наоборот, сценарий «бей или беги» при встрече с источником опасности и сильного стресса.
В 1933 году американский психолог Гордон Уиллард Олпорт описал паттерн поведения как шаблон действий и реакций, который строится на стереотипном представлении ситуации и возможных действий . По мнению Олпорта, само появление поведенческих шаблонов вызвано стремлением человеческого мозга к упрощению и ускорению когнитивных процессов, поэтому для экономии времени он просто выбирает линию поведения, подходящую к той или иной ситуации. Стереотип формируется человеком в течение жизни или закладывается культурным кодом сообщества (как, например, правила этикета) .
Однако по мере развития психологии и этологии ❓ Область зоологии, посвященная изучению генетически обусловленного поведения у животных. ученые начали добавлять к паттерну новые составные части:

Условный рефлекс
Приобретенные через обучение, поощрение или наказание линии поведения, которые человек может неосознанно пронести через всю жизнь.

Инстинктивное поведение
Этот тип поведения закладывается у человека генетически и наследуется в течение многих поколений. Инстинктивным поведением может быть агрессия в состоянии беспомощности или желание убежать, когда на вас смотрит человек в форме, даже если вы ничего не сделали.
Вместе со стереотипом они образуют комплексную структуру, которая, с одной стороны, объединяет людей в группы, а с другой — поведенческий паттерн одновременно индивидуален для каждого человека. Иногда стереотип может пересиливать инстинкт, и, несмотря на чувство страха, агрессии или привязанности, человек сдерживает себя и выбирает нейтрально-дружелюбную линию поведения . А порой стереотип бессилен, когда человек попадает в новую для себя среду, и в дело вступают инстинкты и рефлексы.
Виды паттернов
Паттерн может быть как общим шаблоном поведения человека, так и ситуативным сценарием. В течение одного дня мы используем множество паттернов , которые будут зависеть от обстоятельств (поведение человека в метро отличается от поведения в торговом центре), социальной роли и образа жизни. Ученые выделяют несколько типов паттернов:
- Социальные — универсальны для окружения человека (это традиции и ритуалы);
- Индивидуальные — личные характеристики человека, такие как чувство юмора или манера общения с друзьями;
- Врожденные — инстинкты и безусловные рефлексы;
- Приобретенные — шаблоны поведения, полученные в результате обучения;
- Позитивные — то, что положительно влияет на жизнь: привычка чистить зубы утром и вечером, не использовать слова-паразиты или приверженность здоровому питанию;
- Негативные — обычно к этой группе паттернов относят деструктивное поведение (вредные привычки, необоснованный риск своей жизнью и здоровьем), дисфункциональную коммуникацию, неоправданную агрессию и так далее.
Все эти виды паттернов существуют одновременно и могут спокойно уживаться в одном сценарии поведения . Например, привычка пить кофе вполне может быть одновременно социальным и индивидуальным, приобретенным паттерном. Позитивный он или негативный, зависит от того, сколько кофе вы пьете и как он влияет на ваш организм.
Определять свои и чужие поведенческие паттерны — это навык, который помогает глубже понимать себя и своего собеседника. Таким образом можно строить качественную коммуникацию, выигрывать переговоры и даже найти способ изменить свой образ жизни, понимая его причины.
Поведенческие паттерны проектирования
Список поведенческих паттернов проектирования, которые решают задачи эффективного и безопасного взаимодействия между объектами программы.
Позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи.
Превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их, а также поддерживать отмену операций.
Даёт возможность последовательно обходить элементы составных объектов, не раскрывая их внутреннего представления.
Позволяет уменьшить связанность множества классов между собой, благодаря перемещению этих связей в один класс-посредник.
Позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая подробностей их реализации.
Создаёт механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах.
Позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта.
Определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
Определяет скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.
Позволяет добавлять в программу новые операции, не изменяя классы объектов, над которыми эти операции могут выполняться.

- Премиум контент
- Книга о паттернах
- Курс по рефакторингу
- Введение в рефакторинг
- Чистый код
- Технический долг
- Когда рефакторить
- Как рефакторить
- Раздувальщики
- Длинный метод
- Большой класс
- Одержимость элементарными типами
- Длинный список параметров
- Группы данных
- Операторы switch
- Временное поле
- Отказ от наследства
- Альтернативные классы с разными интерфейсами
- Расходящиеся модификации
- Стрельба дробью
- Параллельные иерархии наследования
- Комментарии
- Дублирование кода
- Ленивый класс
- Класс данных
- Мёртвый код
- Теоретическая общность
- Завистливые функции
- Неуместная близость
- Цепочка вызовов
- Посредник
- Неполнота библиотечного класса
- Составление методов
- Извлечение метода
- Встраивание метода
- Извлечение переменной
- Встраивание переменной
- Замена переменной вызовом метода
- Расщепление переменной
- Удаление присваиваний параметрам
- Замена метода объектом методов
- Замена алгоритма
- Перемещение метода
- Перемещение поля
- Извлечение класса
- Встраивание класса
- Сокрытие делегирования
- Удаление посредника
- Введение внешнего метода
- Введение локального расширения
- Самоинкапсуляция поля
- Замена простого поля объектом
- Замена значения ссылкой
- Замена ссылки значением
- Замена поля-массива объектом
- Дублирование видимых данных
- Замена однонаправленной связи двунаправленной
- Замена двунаправленной связи однонаправленной
- Замена магического числа символьной константой
- Инкапсуляция поля
- Инкапсуляция коллекции
- Замена кодирования типа классом
- Замена кодирования типа подклассами
- Замена кодирования типа состоянием/стратегией
- Замена подкласса полями
- Разбиение условного оператора
- Объединение условных операторов
- Объединение дублирующихся фрагментов в условных операторах
- Удаление управляющего флага
- Замена вложенных условных операторов граничным оператором
- Замена условного оператора полиморфизмом
- Введение Null-объекта
- Введение проверки утверждения
- Переименование метода
- Добавление параметра
- Удаление параметра
- Разделение запроса и модификатора
- Параметризация метода
- Замена параметра набором специализированных методов
- Передача всего объекта
- Замена параметра вызовом метода
- Замена параметров объектом
- Удаление сеттера
- Сокрытие метода
- Замена конструктора фабричным методом
- Замена кода ошибки исключением
- Замена исключения проверкой условия
- Подъём поля
- Подъём метода
- Подъём тела конструктора
- Спуск метода
- Спуск поля
- Извлечение подкласса
- Извлечение суперкласса
- Извлечение интерфейса
- Свёртывание иерархии
- Создание шаблонного метода
- Замена наследования делегированием
- Замена делегирования наследованием
- Введение в паттерны
- Что такое Паттерн?
- История паттернов
- Зачем знать паттерны?
- Критика паттернов
- Классификация паттернов
- Фабричный метод
- Абстрактная фабрика
- Строитель
- Прототип
- Одиночка
- Адаптер
- Мост
- Компоновщик
- Декоратор
- Фасад
- Легковес
- Заместитель
- Цепочка обязанностей
- Команда
- Итератор
- Посредник
- Снимок
- Наблюдатель
- Состояние
- Стратегия
- Шаблонный метод
- Посетитель
- C#
- C++
- Go
- Java
- PHP
- Python
- Ruby
- Rust
- Swift
- TypeScript
Поведенческие паттерны проектирования: для каких задач нужны, виды и примеры реализации
В этой части материала про паттерны разбираемся, что такое поведенческие паттерны проектирования и какие задачи они решают, а также изучаем три самых часто используемых.

Еще раз про паттерны
Паттерны проектирования — это решения распространенных проблем при разработке приложений. Также они известны как шаблоны проектирования, паттерны объектно-ориентированного программирования и design patterns. В отличие от готовых функций или библиотек, паттерн представляет собой не конкретный код, а общую концепцию решения проблемы, которую еще нужно подстроить под задачи.
Всего существует 23 классических паттерна, которые были описаны в книге «Банды четырех». В зависимости от того, какие задачи они решают, делятся на порождающие, структурные и поведенческие.
Поведенческие паттерны
Согласно Википедии, поведенческие шаблоны (behavioral patterns) — шаблоны проектирования, определяющие алгоритмы и способы реализации взаимодействия различных объектов и классов.
Проще говоря, поведенческие паттерны связаны с распределением обязанностей между объектами и описывают структуру и шаблоны для передачи сообщений / связи между компонентами.
К ним относятся:
- Template Method, или Шаблонный метод;
- Iterator, или Итератор;
- Observer, или Наблюдатель;
- Chain of Responsibility, или Цепочка обязанностей;
- Command, или Команда;
- Mediator, или Посредник;
- Memento, или Хранитель;
- Visitor, или Посетитель;
- Strategy, или Стратегия;
- State, или Состояние.
3 самых популярных структурных паттерна
По мнению разработчиков MediaSoft Template Method, Iterator и Observer — самые используемые поведенческие паттерны в разработке. Давайте разберемся, с какими задачами они помогают справляться, и посмотрим на примеры их реализации.
Template Method (Шаблонный метод)
Согласно Википедии, Template Method — поведенческий шаблон проектирования, определяющий основу алгоритма и позволяющий наследникам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом.
Проще говоря, Template Method или шаблонный метод описывает скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.
Еще проще: Строители используют подход, похожий на шаблонный метод, при строительстве типовых домов. У них есть основной архитектурный проект, в котором расписаны шаги строительства: заливка фундамента, постройка стен, перекрытие крыши, установка окон и так далее. Но, несмотря на стандартизацию каждого этапа, строители могут вносить небольшие изменения на любом из этапов, чтобы сделать дом чуточку непохожим на другие.
Когда нужен: используется для избежания дублирования кода. Например, при описании шаблонов.
Паттерн состоит из двух частей:
- Абстрактный класс, который описывает общие свойства и методы.
- Конкретный класс, который переопределяет методы описанные в абстрактном классе или добавляет свои.
Как создать:
- Создать абстрактный класс.
- В нем создать абстрактные методы (шаги алгоритма) и final-метод, вызывающий абстрактные методы (структура алгоритма)
- Создать реализацию абстрактного класса и переопределить абстрактные методы.
Пример реализации:
abstract class AbstractHouse < public final void build() < pourFoundation(); putTheDoor(); buildRoof(); >private void pourFoundation() < System.out.println("Заливка фундамента"); >abstract void putTheDoor(); abstract void buildRoof(); > public class ConcreteHouse extends AbstractHouse < @Override void putTheDoor() < System.out.println("Вставка деревянной двери"); >@Override void buildRoof() < System.out.println("Постройка крыши с окном"); >>// создаем абстрактный класс Car, которому присваиваем общее свойство // cost и метод getCost class Car < constructor(cost) < this.cost = cost; >getCost() < return `Стоимость автомобиля: $`; > > // создаем подклассы от класса Car, которые расширяют // его поведение class SportCar extends Car < constructor(cost, speed) < super(cost); this.speed = speed; >getSpeed() < return `Скорость: $` > > class Truck extends Car < constructor(cost, capacity) < super(cost); this.capacity = capacity; >getCapacity() < return `Вместимость: $` > > const sport = new SportCar(16000, 300); const truck = new Truck(20000, 1000); // как мы видим, теперь у инстанса класса SportCar // есть метод getSpeed, а у инстанса Truck метод // getCapacity, но также у обоих инстансов есть // метод абстрактного класса Car console.log(sport.getCost()); // Стоимость автомобиля: 16000 console.log(sport.getSpeed()); // Скорость: 300 console.log(truck.getCapacity()); // Вместимость: 1000Iterator (Итератор)
Согласно Википедии, Iterator — поведенческий шаблон проектирования. Представляет собой объект, позволяющий получить последовательный доступ к элементам объекта-агрегата без использования описаний каждого из агрегированных объектов.
Проще говоря, Iterator нужен для последовательного перебора составных элементов коллекции, не раскрывая их внутреннего представления.
Еще проще: представим, что мы пошли в лес с множеством красивых мест. Мы хотим посетить конкретные места, например, озеро и поляну цветов, но в лесу очень просто заблудиться. У нас есть несколько вариантов, как дойти до мест: можем воспользоваться бумажной картой или навигатором, попробовать найти все места самим или попросить лесника провести нас. В данном примере, лес — это коллекция живописных мест, а телефон, карта, лесник и наш мозг — итераторы по коллекции «лес».
Когда нужен: Iterator стоит использовать для перебора сложных составных объектов коллекции, если необходимо скрыть детали реализации от клиента.
Структура паттерна:
- Итератор — описывает интерфейс для доступа и обхода элементов коллекции.
- Конкретный итератор — реализует алгоритм обхода какой-то конкретной коллекции.
Как создать:
- Создать интерфейс с методами перемещения по элементам коллекции: получения следующего элемента, проверки наличия следующего элемента, перемещения на первый и последний элемент
- Создать класс реализации интерфейса итератора для конкретного типа коллекции
Пример реализации:
interface Iterator < T next(); void first(); void last(); boolean hasNext(); >public class ListIterator implements Iterator < private Listlist; private int index = 0; public ListIterator(List list) < this.list = list; >public void first() < index = 0; >public void last() < index = list.size(); >public T next() < T obj = list.get(index); index++; return obj; >public boolean hasNext() < return index < list.size(); >>class Iterator < constructor(data) < this.index = 0; this.data = data; >next() < if(this.hasNext()) < return < value: this.data[this.index++], done: false >> return < value: undefined, done: true >> hasNext() < return this.index < this.data.length; >> const cars = ['BMW', 'Audi', 'Honda']; const carsIterator = new Iterator(cars); console.log(carsIterator.next()); // console.log(carsIterator.next()); // console.log(carsIterator.hasNext()); // true console.log(carsIterator.next()); // console.log(carsIterator.hasNext()); // falseObserver (Наблюдатель)
Согласно Википедии, Observer — поведенческий шаблон проектирования. Реализует у класса механизм, который позволяет объекту этого класса получать оповещения об изменении состояния других объектов и тем самым наблюдать за ними.
Проще говоря, Observer позволяет одному объекту подписываться на другие объекты и отслеживать их изменения
Еще проще: после того как вы оформили подписку на газету или журнал, вам больше не нужно ездить в супермаркет и проверять, вышел ли очередной номер. Издательство будет присылать новые номера по почте прямо к вам домой сразу после их выхода.
Когда нужен: часто используется при проектировании библиотек, которые управляют состоянием приложения. Также является основой для различных классов, способных реагировать на изменения и уведомлять своих подписчиков об этих изменениях: например, NotificationCenter в iOS или LiveData в Android.
Структура паттерна:
Паттерн подразумевает наличие трех участников:
- подписчик (subscriber), являющийся интерфейсом/протоколом, который определяет методы для отправки оповещения;
- издатель (publisher), внутреннее состояние которого интересует подписчиков; именно издатель содержит механизм подписки, который включает в себя список подписчиков и методы для подписки/отписки;
- конкретные подписчики (concrete subscribers), реализующие интерфейс/протокол подписчика и несущие в себе конкретную бизнес-логику.
Как создать:
- Создаем наблюдаемый (observable) объект, а точнее субъект (subject), который должен предоставлять интерфейс для регистрации и дерегистрации наблюдателей (listeners).
- Создаем один или несколько наблюдателей, которые должны обладать открытым методом, через который будет происходить оповещение об изменении состояния субъекта. Этот метод часто называют notify.
- Если наблюдателей достаточно много, для упрощения работы с ними можно использовать коллекцию (collection of observers).
Пример реализации:
interface Observable < void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); >class ConcreteObservable implements Observable < private Listparishioners = new ArrayList<>(); private String newsChurch; public void setNewsChurch(String news) < this.newsChurch = news; notifyObservers(); >public void registerObserver(Observer o) < parishioners.add(o); >public void removeObserver(Observer o) < parishioners.remove(o); >public void notifyObservers() < parishioners.forEach(o ->o.update(newsChurch)); > > interface Observer < void update(String news); >public class ConcreteObserver implements Observer < private String name; public ConcreteObserver(String name, Observable o) < this.name = name; o.registerObserver(this); >public void update(String news) < System.out.println(name + " узнал новость: " + news); >>// создаем класс Observer, в котором есть 3 метода // subscribe для добавления подписчиков // unsubscribe для удаления подписчиков // и fire для оповещения подписчиков об изменениях class Observer < constructor() < this.observers = []; >subscribe(fn) < this.observers.push(fn); >unsubscribe(fn) < this.observers = this.observers.filter((subscriber, key) =>subscriber !== fn); > fire(data) < this.observers.forEach(subscriber =>subscriber(data)); > >; let clickCount = 0; const clickObserver = new Observer(); const getMousePosition = (event) => < console.log(`x:$y:$`); >; const getCount = () => < console.log(++clickCount); // обратите внимание на эту часть кода, // здесь мы удаляем подписку при достижении // счетчика 5, и в консоль больше не будет выводиться // значение clickCount if(clickCount === 5) < clickObserver.unsubscribe(getCount); >> // здесь мы добавляем подписчика, который будет // выводить в консоль координаты мышки во // время клика clickObserver.subscribe(getMousePosition); // здесь мы добавляем подписчика, который будет // увеличивать счетчик на 1 и выводить его результат в консоль clickObserver.subscribe(getCount); // далее добавляем событие, при котором observer // будет вызывать всех подписчиков и передавать им // event document.addEventListener('click', (event) => < clickObserver.fire(event); >);Заключение
Паттерны проектирования — это решения распространенных проблем при разработке кода. Их знание и использование позволяет экономить время, используя готовые решения, стандартизировать код и повысить общий словарь.
В зависимости от того, какие задачи решают паттерны проектирования, они делятся на три вида: порождающие, структурные и поведенческие.
Поведенческие паттерны связаны с распределением обязанностей между объектами и описывают структуру и шаблоны для передачи сообщений / связи между компонентами.
Три самых популярных из них:
Template Method, или Шаблонный метод, описывает скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.
Iterator, или Итератор, нужен для последовательного перебора составных элементов коллекции без раскрытия их внутреннего представления. Стоит использовать для перебора сложных составных объектов коллекции, если необходимо скрыть детали от клиента.
Observer, или Наблюдатель, позволяет одному объекту подписываться на другие объекты и отслеживать их изменения. Часто используется при проектировании библиотек, которые управляют состоянием приложения. Также является основой для различных классов, способных реагировать на изменения и уведомлять своих подписчиков об этих изменениях
Поведенческие паттерны что это
Что такое работа мечты и как ее найти. В среднем человек проводит на работе треть жизни и будет глупо посвящать это время нелюбимому делу
Что такое благодарность и как она помогает?
Что такое благодарность? Это добродетель или инструмент саморазвития? 4 секрета благодарности Брайана Трейси. Техники, которые научат говорить слова благодарности.
Что такое ощущение и как его развить?
Что такое ощущения и почему их важно практиковать? Как продлить ощущение счастья?Тактильные ощущения и 7 советов для сверхчувствительных людей.
Что такое кураж и как его поймать?
Что такое кураж? Почему состояние куража означает превзойти свои физические и эмоциональные возможности? 8 техник чтобы войти в кураж .
Что такое расстановки по Хеллингеру и как работает метод?
Что такое расстановки по Хеллингеру? Работающие законы семейных расстановок. Положительные и отрицательные стороны метода.
Что такое деградация и как ее избежать?
Что такое деградация личности и как она происходит? 6 неожиданных советов для тех, кто решил взбодрить мозг и мышление.
Что такое энтузиазм и зачем он нужен?
Что такое энтузиазм? Он является неожиданным вдохновением или контролируемым состоянием? 10 советов о том, как развить в себе энтузиазм
Что такое пофигизм и какие бывают пофигисты?
Что такое пофигизм и почему это понятие считают негативным? Какие виды пофигиза бывают и все ли они он так плохи как кажутся? 3 способа, как стать пофигистом
Кто такой педант и его преимущества и недостатки?
Кто такой педант и почему он отличается повышенной опрятностью, точностью и скрупулезностью. Уделяет внимание мелочам, проявляет усидчивость
Кто такой зануда и что с этим делать?
Кто такой зануда и почему он бывает вполне безобидным, но может сильно действовать на нервы? Как распознать в себе зануду и как перестать им быть?
Что такое ностальгия и как перестать ностальгировать?
Что такое ностальгия как психологический, философский, социологический и маркетинговый термин? 3 совета о том, как сделать ностальгию ресурсным состоянием.
Что такое обстоятельство и как перестать быть его жертвой?
Что такое обстоятельство? В чем разница реактивного и проактивного поведения? Вопросы для выявления в себе добровольной жертвы обстоятельств.