Паттерны проектирования программного обеспечения.

7-11-2019

Паттерн проектирования — это часто встречающееся решение некоторой проблемы при разработке программного обеспечения (ПО).

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

Классификация паттернов

Основными видами паттернов являются:

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

Принципы SOLID

Рассмотрим пять принципов проектирования, которые известны как SOLID. Термин SOLID — это аббревиатура, за каждой буквой которой стоит отдельный принцип проектирования. Главная цель этих принципов — повысить гибкость архитектуры, уменьшить связанность между её компонентами и облегчить повторное использование кода.

  • S: Single Responsibility Principle (Принцип единственной ответственности)
  • O: Open/closed Principle (Принцип открытости/закрытости)
  • L: Liskov Substitution Principle (Принцип подстановки Лисков)
  • I: Interface Segregation Principle (Принцип разделения интерфейса)
  • D: Dependency Inversion Principle (Принцип инверсии зависимостей)

Single Responsibility Principle (Принцип единственной ответственности)

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

Open/closed Principle (Принцип открытости/закрытости)

Стремитесь к тому, чтобы классы были открыты для расширения, но закрыты для изменения. Главная идея этого принципа в том, чтобы не ломать существующий код при внесении изменений в программу. Класс можно считать открытым, если он доступен для расширения. Класс можно считать закрытым, если он готов для использования другими классами. Это означает, что интерфейс класса уже окончательно определён и не будет изменяться в будущем.

Liskov Substitution Principle (Принцип подстановки Лисков)

Подклассы должны дополнять, а не замещать поведение базового класса.

Interface Segregation Principle (Принцип разделения интерфейса)

Клиенты не должны зависеть от методов, которые они не используют. Принцип разделения интерфейсов говорит о том, что слишком «толстые» интерфейсы необходимо разделять на более маленькие, чтобы клиенты маленьких интерфейсов знали только о методах, которые необходимы им в работе. В итоге при изменении метода интерфейса не должны меняться клиенты, которые этот метод не используют.

Dependency Inversion Principle (Принцип инверсии зависимостей)

Классы верхних уровней не должны зависеть от классов нижних уровней. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Классы нижнего уровня реализуют базовые операции вроде подключения к базе данных и прочее.

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

Часто сперва проектируются классы нижнего уровня, а только потом создаются верхнеуровневые классы. При таком подходе классы бизнес-логики становятся зависимыми от более примитивных низкоуровневых классов.

Принцип инверсии зависимостей предлагает изменить направление, в котором происходит проектирование.

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

Паттерны этого типа отвечают за удобное и безопасное создание новых объектов.

Фабричный метод (Factory Method)

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

Абстрактная фабрика (Abstract Factory)

Позволяет создавать семейства связанных объектов, не привязываясь к конкретным классам создаваемых объектов.

Строитель (Builder)

Позволяет создавать сложные объекты пошагово. Строитель даёт возможность использовать один и тот же код строительства для получения разных представлений объектов.

Прототип (Prototype)

Позволяет копировать объекты, не вдаваясь в подробности их реализации.

Одиночка (Singleton)

Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.

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

Эти паттерны отвечают за построение удобных в поддержке иерархий классов.

Адаптер (Adapter)

Позволяет объектам с несовместимыми интерфейсами работать вместе. Это объект-переводчик, который трансформирует интерфейс или данные одного объекта в такой вид, чтобы он стал понятен другому объекту.

Мост (Bridge)

Разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию,позволяя изменять их независимо друг от друга. Паттерн Мост предлагает заменить наследование агрегацией или композицией. Для этого нужно выделить одну из таких «плоскостей» в отдельную иерархию и ссылаться на объект этой иерархии, вместо хранения его состояния и поведения внутри одного класса.

Компоновщик (Composite)

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

Декоратор (Decorator)

Позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки».

Фасад (Facade)

Предоставляет простой интерфейс к сложной системе классов, библиотеке или фреймворку.

Легковес (Flyweight)

Позволяет вместить бóльшее количество объектов в отведённую оперативную память. Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения оди- наковых данных в каждом объекте.

Заместитель (Proxy)

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

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

Эти паттерны решают задачи эффективного и безопасного взаимодействия между объектами программы.

Цепочка обязанностей (Chain of Responsibility)

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

Команда (Command)

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

Итератор (Iterator)

Даёт возможность последовательно обходить элементы составных объектов, не раскрывая их внутреннего представления.

Посредник (Mediator)

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

Снимок (Memento)

Позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая подробностей их реализации.

Наблюдатель (Observer)

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

Состояние (State)

Позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта.

Стратегия (Strategy)

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

Шаблонный метод (Template Method)

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

Посетитель (Visitor)

Позволяет добавлять в программу новые операции, не изменяя классы объектов, над которыми эти операции могут выполняться.

Подробнее с патернами Вы сможете ознакомиться здесь