Паттерны в разработке — что это?
В этой статье поговорим о том, что такое паттерны проектирования, какие они бывают, для чего нужны. Материал будет полезен начинающим программистам.
Паттерны — это способ построения (структуризации) программного кода специальным образом. На практике они используются программистами для того, чтобы решить какую-нибудь проблему, устранить определенную «боль» разработчика. В этом случае предполагается, что существует некоторый перечень общих формализованных проблем (а это так и есть), причем данные проблемы встречаются относительно часто. И вот здесь-то на сцену и выходят паттерны, которые как раз таки и предоставляют способы решения этих проблем.
Немного истории
Сама по себе тема паттернов не является новой. Непосредственная идея по созданию принципов, описывающих решение распространенных в программировании/проектировании ПО проблем, появилась в далеком 1994 году. Именно в этом году в свет вышла известная книга «Design Patterns: Elements of Reusable Object-Oriented Software». Работа была создана целым авторским коллективом, который иногда называют «Gang of Four» (сокращенно GoF) — «Банда четырех». На деле это опытные инженеры-разработчики, вот их имена:
- Ральф Джонсон,
- Ричард Хелм,
- Эрих Гамма,
- Джон Влиссидес.
Книга, о которой идет речь, — это первая серьезная попытка описать наиболее распространенные способы проектирования программного обеспечения. Спустя некоторое время, использование паттернов стало не прихотью разработчика, а хорошей практикой программирования.
Какова польза?
Но существует ли реальный профит от использования паттернов? При грамотном применении — безусловно. Когда вы пишете программный код, вы можете формализовать проблему в виде объектов, классов и соответствующих связей между ними. Когда проблема формализована, для ее решения останется задействовать один из существующих паттернов. Это экономит время программиста, ведь не надо изобретать велосипед и что-нибудь придумывать. Готовый pattern (способ решения) уже существует — нужно лишь правильно применить его в конкретной программе.
Важный момент — использование того либо иного паттерна практически не зависит от языка программирования, системы или интерфейса. То есть принципы применения паттернов проектирования в Java, С-шарп и прочих языках будут аналогичными.
Подведем некоторый промежуточный итог: активное использование паттернов упрощает разработку программ. Есть и другой плюс: если программист, который столкнется с чужим кодом, знает примененный паттерн проектирования и его принципы, ему будет проще понять реализацию и внести изменения в код в случае надобности.
Но у этой медали есть и другая сторона. Да, хорошая программа может подразумевать использование шаблонов проектирования. Но может и не подразумевать. А все потому, что не всегда они позволяют упрощать и улучшать программный код. То есть речь идет о том, что использовать паттерны везде и всюду, то есть применять паттерны ради самих паттернов — это явно плохая практика. Не стоит забывать, что неоправданное применение усложнит код, снизит его качество. Просто помните, что pattern ВСЕГДА должен быть оправданным — и лишь в этом случае он сможет эффективно решить проблему.
Сегодня существует очень много разных паттернов. Они решают различные вопросы, выполняют разные задачи. И действует они по-разному, поэтому их можно классифицировать по группам. В основе такой классификации и объединения в группы будут лежать поставленные цели и решаемые задачи.
Порождающие паттерны
Порождающие паттерны абстрагируют процесс инстанцирования (процесс порождения классов и объектов). Вот их список:
- Abstract Factory — «Абстрактная фабрика»;
- Builder — «Строитель»;
- Factory Method — «Фабричный метод»;
- Prototype — «Прототип»;
- Singleton — «Одиночка».
Структурные паттерны
В этой группе рассматривается, каким образом классы и объекты формируют более крупные структуры (речь идет о более сложных по характеру классах и создаваемых объектах). Перечень структурных шаблонов:
Поведенческие паттерны
Группа под номером 3 объединяет шаблоны, связанные с поведением. Они определяют алгоритмы взаимодействия между объектами и классами, то есть их поведение. Вот перечень наиболее популярных поведенческих паттернов:
- Chain of responsibility — «Цепочкаобязанностей»;
- Command — «Команда»;
- Interpreter — «Интерпретатор»;
- Iterator — «Итератор»;
- Mediator — «Посредник»;
- Memento — «Хранитель»;
- Observer — «Наблюдатель»;
- State — «Состояние»;
- Strategy — «Стратегия»;
- Template method — «Шаблонный метод»;
- Visitor — «Посетитель».
Другие классификации
В зависимости от того, относится pattern к объектам или классам, существуют и другие классификации паттернов.
К примеру, паттерны классов описывают взаимодействие между классами с помощью наследования, причем эти отношения определяются на этапе компиляции. Вот примеры:
Следующая группа — это паттерны объектов, описывающие взаимодействие между объектами. Отношения такого характера возникают на стадии выполнения, следовательно, они более гибкие. Примеры:
Мы перечислили лишь основные варианты, но в реальности их намного больше. Некоторые только начали использоваться, некоторые переживают пик популярности, а некоторые, наоборот, стали применяться реже.
Как сделать правильный выбор?
Прежде чем принять какое-либо решение, следует выделить используемые сущности, а также связи между этими сущностями, после чего необходимо абстрагировать сущности от конкретной ситуации. Получив некую абстрактную форму, посмотрите, вписывается ли она в какой-нибудь из существующих паттернов. К примеру, если смысл решаемой задачи заключается в создании новых объектов, то стоит обратить внимание на порождающие паттерны. Это значит, что следует взять несколько родственных шаблонов из соответствующей группы и определить, какой из них подходит в большей мере с учетом поставленной задачи.
То есть разработчику не только важно понимать смысл и назначение шаблона, но и явно представлять его абстрактную организацию, плюс возможные конкретные реализации, ведь они могут быть разными для одного и того же паттерна. С практикой, чем чаще сталкиваешься с различными реализациями, тем лучше знаешь и понимаешь непосредственный смысл шаблона. Но если вы его не понимаете, использовать его нежелательно, причем даже в том случае, если поначалу кажется, что это именно то, что необходимо именно сейчас.
Вывод прост: придерживайтесь известного принципа KISS (Keep It Simple, Stupid), то есть сохраняйте программный код простым и ясным настолько, насколько это возможно. Иначе теряется весь смысл паттернов проектирования, который заключается именно в упрощении программы.
Хотите поработать с популярными шаблонами проектирования для Java? Желаете попробовать поработать с паттернами для C#? Обратите внимание на наши продвинутые https://otus.ru/catalog/courses?categories=programming на Java и C#:
Также в Otus существует специальный курс «Архитектура и шаблоны проектирования », посвященный паттернам. Не пропустите!
Что такое Паттерн?
Паттерн проектирования — это часто встречающееся решение определённой проблемы при проектировании архитектуры программ.
В отличие от готовых функций или библиотек, паттерн нельзя просто взять и скопировать в программу. Паттерн представляет собой не какой-то конкретный код, а общую концепцию решения той или иной проблемы, которую нужно будет ещё подстроить под нужды вашей программы.
Паттерны часто путают с алгоритмами, ведь оба понятия описывают типовые решения каких-то известных проблем. Но если алгоритм — это чёткий набор действий, то паттерн — это высокоуровневое описание решения, реализация которого может отличаться в двух разных программах.
Если привести аналогии, то алгоритм — это кулинарный рецепт с чёткими шагами, а паттерн — инженерный чертёж, на котором нарисовано решение, но не конкретные шаги его реализации.
Из чего состоит паттерн?
Описания паттернов обычно очень формальны и чаще всего состоят из таких пунктов:
- проблема, которую решает паттерн;
- мотивации к решению проблемы способом, который предлагает паттерн;
- структуры классов, составляющих решение;
- примера на одном из языков программирования;
- особенностей реализации в различных контекстах;
- связей с другими паттернами.
Такой формализм в описании позволил создать обширный каталог паттернов, проверив каждый из них на состоятельность.
- Премиум контент
- Книга о паттернах
- Курс по рефакторингу
- Введение в рефакторинг
- Чистый код
- Технический долг
- Когда рефакторить
- Как рефакторить
- Раздувальщики
- Длинный метод
- Большой класс
- Одержимость элементарными типами
- Длинный список параметров
- Группы данных
- Операторы switch
- Временное поле
- Отказ от наследства
- Альтернативные классы с разными интерфейсами
- Расходящиеся модификации
- Стрельба дробью
- Параллельные иерархии наследования
- Комментарии
- Дублирование кода
- Ленивый класс
- Класс данных
- Мёртвый код
- Теоретическая общность
- Завистливые функции
- Неуместная близость
- Цепочка вызовов
- Посредник
- Неполнота библиотечного класса
- Составление методов
- Извлечение метода
- Встраивание метода
- Извлечение переменной
- Встраивание переменной
- Замена переменной вызовом метода
- Расщепление переменной
- Удаление присваиваний параметрам
- Замена метода объектом методов
- Замена алгоритма
- Перемещение метода
- Перемещение поля
- Извлечение класса
- Встраивание класса
- Сокрытие делегирования
- Удаление посредника
- Введение внешнего метода
- Введение локального расширения
- Самоинкапсуляция поля
- Замена простого поля объектом
- Замена значения ссылкой
- Замена ссылки значением
- Замена поля-массива объектом
- Дублирование видимых данных
- Замена однонаправленной связи двунаправленной
- Замена двунаправленной связи однонаправленной
- Замена магического числа символьной константой
- Инкапсуляция поля
- Инкапсуляция коллекции
- Замена кодирования типа классом
- Замена кодирования типа подклассами
- Замена кодирования типа состоянием/стратегией
- Замена подкласса полями
- Разбиение условного оператора
- Объединение условных операторов
- Объединение дублирующихся фрагментов в условных операторах
- Удаление управляющего флага
- Замена вложенных условных операторов граничным оператором
- Замена условного оператора полиморфизмом
- Введение Null-объекта
- Введение проверки утверждения
- Переименование метода
- Добавление параметра
- Удаление параметра
- Разделение запроса и модификатора
- Параметризация метода
- Замена параметра набором специализированных методов
- Передача всего объекта
- Замена параметра вызовом метода
- Замена параметров объектом
- Удаление сеттера
- Сокрытие метода
- Замена конструктора фабричным методом
- Замена кода ошибки исключением
- Замена исключения проверкой условия
- Подъём поля
- Подъём метода
- Подъём тела конструктора
- Спуск метода
- Спуск поля
- Извлечение подкласса
- Извлечение суперкласса
- Извлечение интерфейса
- Свёртывание иерархии
- Создание шаблонного метода
- Замена наследования делегированием
- Замена делегирования наследованием
- Введение в паттерны
- Что такое Паттерн?
- История паттернов
- Зачем знать паттерны?
- Критика паттернов
- Классификация паттернов
- Фабричный метод
- Абстрактная фабрика
- Строитель
- Прототип
- Одиночка
- Адаптер
- Мост
- Компоновщик
- Декоратор
- Фасад
- Легковес
- Заместитель
- Цепочка обязанностей
- Команда
- Итератор
- Посредник
- Снимок
- Наблюдатель
- Состояние
- Стратегия
- Шаблонный метод
- Посетитель
- C#
- C++
- Go
- Java
- PHP
- Python
- Ruby
- Rust
- Swift
- TypeScript
Паттерны проектирования: для чего нужны, какими бывают и чем отличаются от архитектурных
Паттерны проектирования можно обсуждать бесконечно. Основное их назначение в том, что они помогают новичкам и опытным программистам экономить время при разработке, минимизировать количество ошибок и, в целом, выглядеть более грамотным при разговорах с коллегами 🙂
Поэтому вместе с преподавателями Академии мы запускаем серию статей о паттернах. В первой части материала разбираемся, что такое паттерны проектирования, какими бывают и чем отличаются от архитектурных паттернов.
ЧТО ТАКОЕ ПАТТЕРНЫ ПРОЕКТИРОВАНИЯ
Цельное представление о паттернах появилось в 1994 году после выхода нашумевшей книги «Приемы объектно-ориентированного программирования. Паттерны проектирования» от авторов, которых прозвали «Банда четырех».
В книге под паттерном понимается описание взаимодействия объектов и классов, адаптированных для решения общей задачи проектирования в конкретном контексте.
Проще говоря, паттерны проектирования — это решения распространенных проблем при разработке кода. Также они известны как шаблоны проектирования, паттерны объектно-ориентированного программирования или design patterns. В отличие от готовых функций или библиотек, паттерн представляет собой не конкретный код, а общую концепцию решения проблемы, которую еще нужно подстроить под задачи.
Зачем знать паттерны?
- Проверенные решения. Вы тратите меньше времени, используя готовые решения, вместо изобретения велосипеда.
- Стандартизация кода. Вы делаете меньше просчетов при разработке, используя типовые решения, так как все возможные проблемы в них уже найдены.
- Общий программистский словарь. Вместо того, чтобы долго объяснять коллеге логику работы вашего кода, вы называете паттерн, который хотите использовать, и экономите свое и чужое время.
Какими бывают паттерны проектирования
Всего существует 23 классических паттерна, которые были описаны в книге «Банды четырех». В зависимости от того, какие задачи решают паттерны, они делятся на три вида — порождающие, структурные и поведенческие.
Порождающие предназначены для создания экземпляра объекта или группы связанных объектов. К ним относятся:
- Abstract Factory — Абстрактная фабрика
- Builder — Строитель
- Factory Method — Фабричный метод
- Prototype — Прототип
- Singleton — Одиночка
Структурные в основном связаны с композицией объектов, с тем, как сущности могут использовать друг друга. К ним относятся:
- Adapter — Адаптер
- Bridge — Мост
- Composite — Компоновщик
- Decorator — Декоратор
- Facade — Фасад
- Flyweight — Приспособленец
- Proxy — Заместитель
Поведенческие связаны с распределением обязанностей между объектами. Их отличие от структурных шаблонов заключается в том, что они описывают не только структуру, но и способы общения между ними. К ним относятся:
- Chain of responsibility — Цепочка обязанностей
- Command — Команда
- Interpreter — Интерпретатор
- Iterator — Итератор
- Mediator — Посредник
- Memento — Хранитель
- Observer — Наблюдатель
- State — Состояние
- Strategy — Стратегия
- Template method — Шаблонный метод
- Visitor — Посетитель
Паттерны проектирования vs. архитектурные паттерны — в чем разница
Новички могут спутать паттерны проектирования и архитектурные паттерны, так как обычно в разговоре разработчики называют и те, и другие просто паттернами. Давайте разберемся, в чем отличия.
Паттерны проектирования предоставляют решения для доработки и построения подсистем на уровне кода. Обычно на их выбор влияет язык программирования, а разработчик сам принимает решение, какой паттерн использовать.
Архитектурные паттерны (архитектурные шаблоны, architectural patterns) рассматриваются на более высоком уровне. Они определяет архитектуру приложения, задают его логику (на какие компоненты/модули будет делиться приложение и каким образом они взаимодействуют) и помогают разработчику понять, как устроен продукт внутри. Выбор паттернов происходит на этапе создания продукта.
Про многие из архитектурных паттернов вы, скорее всего, уже слышали. Например, клиент-серверная архитектура, шина событий, MVC или интерпретатор. Подробнее про самые популярные паттерны можно прочитать в статье.
Заключение
Паттерны проектирования — это решения распространенных проблем при разработке кода. Их знание и использование позволяет экономить время, используя готовые решения, стандартизировать код и повысить общий программистский словарь.
Основное отличие паттернов проектирования от архитектурных в том, что первые предоставляют решения на уровне кода. Обычно на их выбор влияет язык программирования, а разработчик сам принимает решение, какой паттерн использовать. Архитектурные паттерны определяют архитектуру приложения, задают его логику и помогают разработчику понять, как устроен продукт внутри.
В зависимости от того, какие задачи решают паттерны проектирования, они делятся на три вида: порождающие, структурные и поведенческие. В следующих статьях мы подробнее расскажем про каждый вид и разберем 9 самых популярных паттернов, которыми чаще всего пользуются программисты.
Паттерны проектирования
Паттерны (или шаблоны) проектирования описывают типичные способы решения часто встречающихся проблем при проектировании программ.
Каталог паттернов
Список из 22-х классических паттернов, сгруппированых по предназначению.
Польза паттернов
Вы можете вполне успешно работать, не зная ни одного паттерна. Но зная паттерны, вы получаете ещё один инструмент в свой личный набор профессионала.
Классификация
Паттерны отличаются по уровню сложности, охвата и детализации проектируемой системы. Кроме этого, их можно поделить на три группы, относительно решаемых проблем.
История паттернов
Кто и когда придумал паттерны? Можно ли использовать язык паттернов вне разработки программного обеспечения?
Критика паттернов
Так ли паттерны хороши на самом деле? Всегда ли можно их использовать? Почему, иногда, паттерны бывают вредными?
Погружение в Паттерны
Электронная книга о паттернах и принципах проектирования. Доступна в PDF/EPUB/MOBI. Включает в себя архив с примерами на 9 языках программирования.
- Премиум контент
- Книга о паттернах
- Курс по рефакторингу
- Введение в рефакторинг
- Чистый код
- Технический долг
- Когда рефакторить
- Как рефакторить
- Раздувальщики
- Длинный метод
- Большой класс
- Одержимость элементарными типами
- Длинный список параметров
- Группы данных
- Операторы switch
- Временное поле
- Отказ от наследства
- Альтернативные классы с разными интерфейсами
- Расходящиеся модификации
- Стрельба дробью
- Параллельные иерархии наследования
- Комментарии
- Дублирование кода
- Ленивый класс
- Класс данных
- Мёртвый код
- Теоретическая общность
- Завистливые функции
- Неуместная близость
- Цепочка вызовов
- Посредник
- Неполнота библиотечного класса
- Составление методов
- Извлечение метода
- Встраивание метода
- Извлечение переменной
- Встраивание переменной
- Замена переменной вызовом метода
- Расщепление переменной
- Удаление присваиваний параметрам
- Замена метода объектом методов
- Замена алгоритма
- Перемещение метода
- Перемещение поля
- Извлечение класса
- Встраивание класса
- Сокрытие делегирования
- Удаление посредника
- Введение внешнего метода
- Введение локального расширения
- Самоинкапсуляция поля
- Замена простого поля объектом
- Замена значения ссылкой
- Замена ссылки значением
- Замена поля-массива объектом
- Дублирование видимых данных
- Замена однонаправленной связи двунаправленной
- Замена двунаправленной связи однонаправленной
- Замена магического числа символьной константой
- Инкапсуляция поля
- Инкапсуляция коллекции
- Замена кодирования типа классом
- Замена кодирования типа подклассами
- Замена кодирования типа состоянием/стратегией
- Замена подкласса полями
- Разбиение условного оператора
- Объединение условных операторов
- Объединение дублирующихся фрагментов в условных операторах
- Удаление управляющего флага
- Замена вложенных условных операторов граничным оператором
- Замена условного оператора полиморфизмом
- Введение Null-объекта
- Введение проверки утверждения
- Переименование метода
- Добавление параметра
- Удаление параметра
- Разделение запроса и модификатора
- Параметризация метода
- Замена параметра набором специализированных методов
- Передача всего объекта
- Замена параметра вызовом метода
- Замена параметров объектом
- Удаление сеттера
- Сокрытие метода
- Замена конструктора фабричным методом
- Замена кода ошибки исключением
- Замена исключения проверкой условия
- Подъём поля
- Подъём метода
- Подъём тела конструктора
- Спуск метода
- Спуск поля
- Извлечение подкласса
- Извлечение суперкласса
- Извлечение интерфейса
- Свёртывание иерархии
- Создание шаблонного метода
- Замена наследования делегированием
- Замена делегирования наследованием
- Введение в паттерны
- Что такое Паттерн?
- История паттернов
- Зачем знать паттерны?
- Критика паттернов
- Классификация паттернов
- Фабричный метод
- Абстрактная фабрика
- Строитель
- Прототип
- Одиночка
- Адаптер
- Мост
- Компоновщик
- Декоратор
- Фасад
- Легковес
- Заместитель
- Цепочка обязанностей
- Команда
- Итератор
- Посредник
- Снимок
- Наблюдатель
- Состояние
- Стратегия
- Шаблонный метод
- Посетитель
- C#
- C++
- Go
- Java
- PHP
- Python
- Ruby
- Rust
- Swift
- TypeScript