Встречается на 25% собеседований по Java

Какие знаешь паттерны проектирования

Паттерны проектирования — это проверенные временем шаблоны решений для часто встречающихся проблем в объектно-ориентированном проектировании. Они не являются готовыми библиотеками или фреймворками, а представляют собой общие концепции, которые помогают сделать код более гибким, модульным и поддерживаемым. Паттерны обычно делят на три категории: порождающие, структурные и поведенческие. Знание этих паттернов и умение применять их в нужном контексте — важный навык для Java-разработчика, так как они лежат в основе многих популярных библиотек и фреймворков (например, Spring, Hibernate).

Порождающие паттерны

Порождающие паттерны управляют процессом создания объектов, делая его более гибким и независимым от конкретных классов. Они помогают скрыть детали инстанцирования и позволяют системе быть независимой от того, как создаются и представляются объекты.

  • Одиночка (Singleton) — гарантирует, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к нему. В Java часто реализуется через приватный конструктор и статический метод getInstance(). Однако следует быть осторожным с многопоточностью — нужна синхронизация или использование enum.
  • Фабричный метод (Factory Method) — определяет интерфейс для создания объекта, но позволяет подклассам изменять тип создаваемых объектов. Это позволяет делегировать создание объектов подклассам.
  • Абстрактная фабрика (Abstract Factory) — предоставляет интерфейс для создания семейств связанных объектов без указания их конкретных классов. Позволяет создавать целые наборы взаимосвязанных объектов, например, для разных операционных систем.
  • Строитель (Builder) — позволяет создавать сложные объекты пошагово, отделяя процесс конструирования от представления. Особенно полезен, когда объект имеет много параметров, некоторые из которых необязательны.
  • Прототип (Prototype) — позволяет копировать существующие объекты без привязки к их конкретным классам. В Java это реализуется через интерфейс Cloneable и метод clone().

Структурные паттерны

Структурные паттерны описывают способы объединения классов и объектов в более крупные структуры, сохраняя при этом гибкость и эффективность. Они помогают упростить архитектуру, обеспечивая правильные отношения между сущностями.

  • Адаптер (Adapter) — позволяет объектам с несовместимыми интерфейсами работать вместе, преобразуя интерфейс одного класса в интерфейс, ожидаемый клиентом.
  • Мост (Bridge) — разделяет абстракцию и реализацию, чтобы они могли изменяться независимо. Это особенно полезно, когда нужно избежать жёсткой связи между интерфейсом и его реализацией.
  • Компоновщик (Composite) — позволяет клиентам единообразно работать с отдельными объектами и их группами. Часто используется для построения древовидных структур, например, в графических редакторах.
  • Декоратор (Decorator) — динамически добавляет объектам новые обязанности, помещая их в обёртки. В Java широко используется ввода-выводе, например, BufferedReader оборачивает FileReader.
  • Фасад (Facade) — предоставляет упрощённый интерфейс к сложной системе классов, библиотеке или фреймворку. Скрывает внутренние детали и уменьшает связанность.
  • Приспособленец (Flyweight) — эффективно поддерживает большое количество мелких объектов, разделяя общее состояние. Применяется для оптимизации памяти, например, при работе со строками в Java.
  • Заместитель (Proxy) — предоставляет заменитель или местозаполнитель для другого объекта, контролируя доступ к нему. Может использоваться для ленивой инициализации, логирования, контроля доступа.

Поведенческие паттерны

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

  • Цепочка обязанностей (Chain of Responsibility) — позволяет передавать запросы последовательно по цепочке обработчиков, пока один из них не обработает запрос. Это уменьшает связанность между отправителем и получателем.
  • Команда (Command) — превращает запросы в объекты, позволяя передавать их как аргументы, ставить в очередь, логировать и поддерживать отмену операций.
  • Итератор (Iterator) — предоставляет способ последовательного доступа к элементам составного объекта, не раскрывая его внутреннее представление. В Java это интерфейс Iterator.
  • Посредник (Mediator) — уменьшает сложность взаимодействия между объектами, вводя централизованный объект-посредник, который управляет связями.
  • Хранитель (Memento) — позволяет сохранять и восстанавливать предыдущее состояние объекта без раскрытия его реализации. Полезен для реализации функций отмены.
  • Наблюдатель (Observer) — позволяет объектам получать уведомления об изменении состояния других объектов. В Java это реализуется через Observer/Observable или через слушатели событий.
  • Состояние (State) — позволяет объекту изменять своё поведение при изменении внутреннего состояния. Внешне выглядит, как будто объект меняет свой класс.
  • Стратегия (Strategy) — определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиента.
  • Шаблонный метод (Template Method) — определяет скелет алгоритма, оставляя подклассам возможность переопределять отдельные шаги без изменения структуры.
  • Посетитель (Visitor) — позволяет добавлять новые операции к объектам без изменения их классов. Это достигается вынесением операции в отдельный объект-посетитель.

Коротко

  • Паттерны делятся на три группы: порождающие (создание объектов), структурные (композиция классов и объектов) и поведенческие (взаимодействие между объектами).
  • Знание паттернов помогает говорить на одном языке с другими разработчиками и быстрее понимать архитектуру популярных фреймворков.
  • На собеседовании важно не только перечислить названия, но и уметь объяснить, какую проблему решает каждый паттерн и привести пример из практики.
  • Не стоит пытаться использовать все паттерны подряд — они должны применяться осознанно, когда есть реальная необходимость в гибкости или расширяемости.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы