Паттерны
Паттерны проектирования: каталог GoF и прикладные паттерны корпоративных приложений.
Группы
creational/— порождающиеstructural/— структурныеbehavioral/— поведенческиеenterprise/— прикладные: Repository, Unit of Work, Specification, Outbox…
Темы
Порождающие
- Абстрактная фабрика (Abstract Factory) — семейство согласованных продуктов создаётся целиком · практика: платёжные провайдеры, возврат уходит тому, кто принял платёж
- Строитель (Builder) — сложный объект по шагам с одной проверкой в конце · практика: неизменяемый строитель SQL-запроса отчёта
- Одиночка (Singleton) — один экземпляр на процесс и глобальная точка доступа, которая почти всегда вредна · практика: тарифы, загруженные один раз, без глобальной точки доступа
- Прототип (Prototype) — новый объект копией настроенного, глубину копии решает сам объект · практика: КП из шаблона, что сбросить, что скопировать, что делить
- Фабричный метод (Factory Method) — создание продукта отдаётся наследникам, общий алгоритм остаётся в базе · практика: импорт прайс-листов с парсером по формату файла · вторая практика: разбор пакетов приборов учёта по типу из заголовка
Структурные
- Адаптер (Adapter) — даёт старому классу интерфейс, которого ждёт клиент, не меняя ни класс, ни клиента · практика: старый SMS-шлюз под интерфейсом уведомлений, перевод форматов номеров и кодов ошибок
- Декоратор (Decorator) — поведение добавляется обёртками с тем же интерфейсом · практика: клиент курсов валют с ретраями, кэшем и журналом, где порядок слоёв меняет поведение · вторая практика: слои над медленным отчётом из конфига, порядок кэша и лимита
- Заместитель (Proxy) — объект с тем же интерфейсом решает, пускать ли вызов к настоящему · практика: кэш репозитория товаров с TTL и сбросом при записи
- Компоновщик (Composite) — дерево из листов и контейнеров с одним интерфейсом · практика: корзина с вложенными наборами, скидка на каждом уровне, проверка каталога на циклы
- Мост (Bridge) — абстракция и реализация растут независимо · практика: отчёты в HTML, CSV и Markdown без N x M классов
- Приспособленец (Flyweight) — тысячи объектов делят немного неизменяемых общих частей · практика: стили ячеек таблицы, пул по ключу и копирование при записи
- Фасад (Facade) — один простой вход в набор подсистем · практика: оформление заказа за одним PlaceOrder с откатом резерва
Поведенческие
- Интерпретатор (Interpreter) — грамматика как дерево выражений, каждый узел вычисляет себя в контексте · практика: мини-язык фильтров товаров, парсер с приоритетами и ошибки с позицией
- Итератор (Iterator) — обход коллекции по одному элементу, не раскрывая её устройства · практика: постраничный обход API заказов с ленивой подгрузкой
- Команда (Command) — запрос как объект: выполнить сейчас, отменить потом · практика: редактор с undo/redo, склейкой набора и неудачными правками вне истории · вторая практика: команды прибору учёта по радио: очередь, подтверждение, повтор по таймауту
- Наблюдатель (Observer) — издатель рассылает изменения подписчикам, не зная, кто они · практика: доменные события заказа, ошибки подписчиков и очередь вместо рекурсии · вторая практика: поток показаний приборов учёта: порог, пропажа связи, суточный расход
- Посетитель (Visitor) — новые операции над классами без их правки · практика: НДС, фискальный чек и проверка заказа посетителями
- Посредник (Mediator) — объекты общаются через посредника, а не друг с другом · практика: форма оформления заказа с правилами в посреднике
- Снимок (Memento) — сохранить и восстановить состояние, не раскрывая внутренностей · практика: черновики анкеты с автосохранением, точками отката и версией формата
- Состояние (State) — объект меняет поведение вместе с состоянием · практика: жизненный цикл заказа, запреты переходов и возврат денег на переходе · вторая практика: плата на производстве: этапы, доработка только с контроля, брак конечный
- Стратегия (Strategy) — взаимозаменяемые алгоритмы за общим контрактом · практика: расчёт доставки по правилам из конфига · вторая практика: наценка по категории из конфига и общие правила цены
- Цепочка обязанностей (Chain of Responsibility) — запрос идёт по цепочке, каждый обрабатывает сам или передаёт дальше · практика: middleware запроса, где порядок звеньев решает · вторая практика: приём вебхуков АТС: подпись, дедупликация повторов, маршрутизатор по типу события
- Шаблонный метод (Template Method) — порядок шагов фиксирует база, наследники подставляют шаги · практика: экспорт платёжного реестра в разные банки
Прикладные
- Доменное событие (Domain Event) — агрегат записывает неизменяемые факты в прошедшем времени · практика: публикация событий только после успешного сохранения, с версией и временем
- Единица работы (Unit of Work) — копит изменения и записывает их одним проходом на commit · практика: перевод и заказ в одной транзакции, identity map и откат при ошибке на середине
- Нулевой объект (Null Object) — нейтральное поведение вместо null и проверок · практика: гость и выключенная аналитика, а ненайденный заказ остаётся ошибкой
- Outbox (Transactional Outbox) — событие пишется в ту же транзакцию, что и данные · практика: отправитель с ретраями и порядком по заказу, идемпотентный получатель · вторая практика: уведомления клиентам в Telegram: пачки, пауза на 429, ключ идемпотентности
- Преобразователь данных (Data Mapper) — модель не знает о хранилище, маппер переводит туда и обратно · практика: заказ с value objects в двух таблицах и ошибка на битых данных
- Репозиторий (Repository) — коллекция сущностей на языке домена · практика: один набор контрактных тестов на память и JSON-файл, конфликт версий · вторая практика: контрагенты из учётной системы за HTTP API: страницы, коды ответа, маппинг полей
- Сервисный слой (Service Layer) — сценарии приложения в одном слое, тонкие входы · практика: регистрация на мероприятие, транзакция вокруг сценария, ошибки ввода и правил разными типами
- Спецификация (Specification) — бизнес-правило как объект с and/or/not · практика: аудитория рассылки, одна спецификация для памяти и для SQL WHERE · вторая практика: доступ к заказу в админке: правило из and/or/not с объяснением отказа
creational/Порождающие
- abstract-factory/Абстрактная фабрика Abstract FactoryСоздаёт семейство связанных объектов целиком, чтобы клиент не мог смешать продукты разных семейств. + практика
- builder/Строитель BuilderСобирает сложный объект по шагам: обязательные части, необязательные в любом порядке, одна проверка в конце. + практика
- factory-method/Фабричный метод Factory MethodОбщий алгоритм живёт в базовом классе, а решение «какой именно объект создать» отдаётся наследникам. + 2 практики
- prototype/Прототип PrototypeНовый объект создаётся копией уже настроенного, а глубину копии решает сам объект. + практика
- singleton/Одиночка SingletonГарантирует один экземпляр на процесс и даёт к нему глобальную точку доступа. Первое полезно, второе почти всегда вредно. + практика
structural/Структурные
- adapter/Адаптер AdapterДаёт старому или чужому классу тот интерфейс, которого ждёт клиент, не меняя ни класс, ни клиента. + практика
- bridge/Мост BridgeРазделяет иерархию на две — абстракцию и реализацию, — чтобы каждая росла сама по себе, а не перемножалась с другой. + практика
- composite/Компоновщик CompositeДерево из простых и составных объектов с одним интерфейсом: клиент спрашивает узел, не выясняя, лист это или контейнер. + практика
- decorator/Декоратор DecoratorДобавляет объекту поведение обёрткой с тем же интерфейсом: обёртки складываются в любом количестве и порядке, а исходный класс не меняется. + 2 практики
- facade/Фасад FacadeДаёт один простой вход в набор подсистем: клиент вызывает одну операцию, а порядок шагов и связи между частями знает фасад. + практика
- flyweight/Приспособленец FlyweightМного мелких объектов делят одно неизменяемое общее состояние, а уникальное хранят у себя или получают параметрами. + практика
- proxy/Заместитель ProxyПодставляет вместо объекта другой с тем же интерфейсом, который решает, когда и пускать ли вызов дальше. + практика
behavioral/Поведенческие
- chain-of-responsibility/Цепочка обязанностей Chain of ResponsibilityПередаёт запрос по цепочке обработчиков: каждый либо обрабатывает его сам, либо отдаёт следующему, и отправитель не знает, кто в итоге ответит. + 2 практики
- command/Команда CommandПревращает запрос в объект: его можно сохранить, передать, выполнить позже и отменить, а тот, кто его запускает, не знает, что именно он делает. + 2 практики
- interpreter/Интерпретатор InterpreterПравила маленького языка становятся деревом объектов, и каждый узел сам вычисляет свою часть выражения. + практика
- iterator/Итератор IteratorДаёт обойти коллекцию по одному элементу, не раскрывая, как она устроена внутри. + практика
- mediator/Посредник MediatorУбирает прямые связи между объектами: каждый говорит только с посредником, а правила их взаимодействия собраны в одном месте. + практика
- memento/Снимок MementoОбъект сохраняет своё состояние в непрозрачный снимок и потом восстанавливается из него, не раскрывая внутренностей тому, кто снимки хранит. + практика
- observer/Наблюдатель ObserverОбъект сообщает об изменениях всем, кто подписался, и не знает, кто они: подписчиков можно добавлять и убирать, не трогая источник. + 2 практики
- state/Состояние StateОбъект меняет поведение вместе со своим состоянием: каждое состояние — отдельный объект, и вместо if (state === ...) в каждом методе контекст просто передаёт вызов текущему состоянию. + 2 практики
- strategy/Стратегия StrategyВыносит семейство взаимозаменяемых алгоритмов в отдельные объекты, чтобы менять их без правки кода, который их использует. + 2 практики
- template-method/Шаблонный метод Template MethodПорядок шагов алгоритма фиксирует базовый класс, а наследники подставляют только сами шаги и, если нужно, меняют поведение крючков. + практика
- visitor/Посетитель VisitorНовые операции над набором классов без правки самих классов: каждая операция живёт в своём объекте, а узел только говорит, какой он. + практика
enterprise/Прикладные
- data-mapper/Преобразователь данных Data MapperОтдельный объект переносит данные между доменной моделью и хранилищем, так что модель не знает ни таблиц, ни колонок, ни того, что её вообще сохраняют. + практика
- domain-event/Доменное событие Domain EventАгрегат записывает, что с ним случилось, в виде неизменяемых фактов в прошедшем времени, а реагируют на эти факты другие части системы: агрегат не знает ни о почте, ни о биллинге. + практика
- null-object/Нулевой объект Null ObjectВместо null подставляет объект с тем же интерфейсом и нейтральным поведением, чтобы код не проверял на null перед каждым вызовом. + практика
- outbox/Outbox Transactional OutboxСобытие о бизнес-изменении записывается в ту же базу и в той же транзакции, что и само изменение, а в брокер его отправляет отдельный процесс: данные и событие не расходятся, даже если брокер лежит. + 2 практики
- repository/Репозиторий RepositoryДаёт предметной области коллекцию сущностей с методами на её языке и прячет за ней, где и как они хранятся. + 2 практики
- service-layer/Сервисный слой Service LayerСобирает сценарии приложения в один слой: контроллер, консольная команда и очередь вызывают один метод сервиса, а не повторяют шаги каждый у себя. + практика
- specification/Спецификация SpecificationБизнес-правило становится отдельным объектом с одним вопросом «подходит ли кандидат», и одно и то же правило проверяет объект, отбирает список и собирается с другими через «и», «или», «не». + 2 практики
- unit-of-work/Единица работы Unit of WorkСобирает все изменения бизнес-операции (новые, изменённые и удалённые объекты) и записывает их в хранилище одним проходом в конце, а не по одному в момент каждой правки. + практика