Паттерны проектирования
В разработке программного обеспечения паттерн проектирования программного обеспечения - это общее, многократно используемое решение часто встречающейся проблемы в данном контексте при разработке программного обеспечения. Это не законченный проект, который может быть преобразован непосредственно в исходный или машинный код. Скорее, это описание или шаблон для решения проблемы, которые можно использовать в самых разных ситуациях. Паттерны проектирования - это формализованные передовые практики, которые программист может использовать для решения общих проблем при разработке приложения или системы.
Паттерны объектно-ориентированного проектирования обычно показывают отношения и взаимодействия между классами или объектами без указания конечных классов приложений или объектов, которые в них участвуют. Паттерны, которые подразумевают изменяемое состояние, могут не подходить для функциональных языков программирования, некоторые паттерны могут быть лишними в языках, которые имеют встроенную поддержку для решения проблемы, которую они пытаются решить, и объектно-ориентированные паттерны не обязательно подходят для не объектно-ориентированных языков.
Паттерны проектирования можно рассматривать как структурированный подход к компьютерному программированию, промежуточный между уровнями парадигмы программирования и конкретным алгоритмом.
История
Паттерны возникли как архитектурная концепция Кристофера Александра (1977/78). В 1987 году Кент Бек и Уорд Каннингем начали экспериментировать с идеей применения паттернов к программированию - в частности, языков паттернов - и представили свои результаты на конференции OOPSLA в этом году. В последующие годы Бек, Каннингем и другие продолжили эту работу.
Паттерны проектирования приобрели популярность в компьютерных науках после того, как книга "Паттерны проектирования: элементы многоразового объектно-ориентированного программного обеспечения" (Design Patterns: Elements of Reusable Object-Oriented Software) была опубликована в 1994 году так называемой "Бандой четырех" ("Gang of Four"), которую часто называют "GoF". В том же году была проведена первая Конференция языков программирования паттернов, а в следующем году был создан репозиторий паттернов Portland для документирования паттернов проектирования. Сфера действия термина остается предметом спора.
Хотя паттерны проектирования применялись практически долгое время, формализация концепции паттернов проектирования ослабла в течение нескольких лет.
Практика
Паттерны проектирования могут ускорить процесс разработки, предоставляя проверенные, одобренные парадигмы разработки. Эффективный дизайн программного обеспечения требует рассмотрения проблем, которые могут стать невидимыми до более поздней стадии реализации. У недавно написанного кода часто могут быть скрытые тонкие проблемы, которые требуют времени для обнаружения, проблемы, которые иногда могут вызвать серьезные проблемы в будущем. Повторное использование паттернов проектирования помогает предотвратить такие тонкие проблемы, а также улучшает читабельность кода для разработчиков и архитекторов, знакомых с паттернами.
Чтобы достичь гибкости, паттерны проектирования обычно вводят дополнительные уровни косвенности, что в некоторых случаях может усложнить получившиеся конструкции и снизить производительность приложений.
По определению, паттерн должен быть запрограммирован заново в каждом приложении, которое его использует. Поскольку некоторые авторы рассматривают это как шаг назад от повторного использования программного обеспечения, предоставляемого компонентами, исследователи работали над превращением паттернов в компоненты. Мейер и Арно смогли обеспечить полную или частичную компонентизацию двух третей паттернов, которые они пытались.
Классификация и список
Паттерны проектирования изначально были сгруппированы по категориям: порождающие паттерны (creational patterns), структурные паттерны (structural patterns) и поведенческие паттерны (behavioral patterns), и описаны с использованием концепций делегирования, агрегирования и консультаций. В другой классификации также введено понятие архитектурного паттерна проектирования, которое может применяться на уровне архитектуры программного обеспечения, например паттерн Модель-Вид-Контроллер (Model–View–Controller).
Порождающие паттерны (Creational patterns)
Абстрактная фабрика (Abstract factory). Предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.
Строитель (Builder). Отделяет конструкцию сложного объекта от его представления, что позволяет одному и тому же процессу конструирования создавать различные представления.
Внедрение зависимостей (Dependency Injection). Класс принимает объекты, которые ему требуются от инжектора, вместо того, чтобы создавать объекты напрямую.
Фабричный метод (Factory method). Определяет интерфейс для создания одного объекта, но предоставляет подклассам решать, какой класс создать. Позволяет классу отложить создание экземпляров для подклассов.
Ленивая инициализация (Lazy initialization). Тактика задержки создания объекта, вычисления значения или какого-либо другого дорогостоящего процесса до тех пор, пока он не понадобится в первый раз. Этот паттерн появляется в каталоге GoF как "виртуальный прокси", стратегия реализации паттерна Proxy.
Мультитон (Multiton). Убеждается, что класс имеет только именованные экземпляры, и предоставляет им глобальную точку доступа.
Пул объектов (Object pool). Избегает дорогостоящих приобретений и высвобождения ресурсов путем утилизации объектов, которые больше не используются. Можно рассматривать как обобщение паттернов пул соединений (connection pool) и пул потоков (thread pool).
Прототип (Prototype). Указывает типы объектов, создаваемых с использованием прототипного экземпляра, и создает новые объекты из "скелета" существующего объекта, тем самым повышая производительность и сводя к минимуму объем памяти.
Получение ресурсов - инициализация (RAII, Resource acquisition is initialization). Убеждается, что ресурсы высвобождаются должным образом, привязав их к сроку службы подходящих объектов.
Синглтон (Singleton). Убеждается, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.
Структурные паттерны (Structural patterns)
Адаптер (Adapter), Обертка (Wrapper) или Транслятор (Translator). Преобразует интерфейс класса в другой интерфейс, ожидаемый клиентами. Адаптер позволяет классам работать вместе, что иначе невозможно из-за несовместимых интерфейсов. Эквивалент паттерна интеграции предприятия (enterprise integration pattern) - Транслятор.
Мост (Bridge). Разъединяет абстракцию от ее реализации, позволяя им изменяться независимо.
Композит (Composite). Составляет объекты в древовидные структуры для представления иерархий части-целого. Композит позволяет клиентам одинаково относиться к отдельным объектам и композициям объектов.
Декоратор (Decorator). Прикрепляет дополнительные обязанности к объекту, динамически поддерживая тот же интерфейс. Декораторы предоставляют гибкую альтернативу подклассам для расширения функциональности.
Объект расширения (Extension object). Добавляет функциональность в иерархию без изменения иерархии.
Фасад (Facade). Предоставляет унифицированный интерфейс для набора интерфейсов в подсистеме. Фасад определяет высокоуровневый интерфейс, который упрощает использование подсистемы.
Приспособленец (Flyweight, Легковесный). Использует общий доступ для эффективной поддержки большого количества похожих объектов.
Фронт-контроллер (Front controller). Паттерн относится к дизайну веб-приложений. Он обеспечивает централизованную точку входа для обработки запросов.
Маркер (Marker). Пустой интерфейс для связи метаданных с классом.
Модуль (Module). Объединение нескольких связанных элементов, таких как классы, синглтоны, методы, используемые глобально, в единую концептуальную сущность.
Прокси (Proxy). Предоставляет суррогат или заполнитель для другого объекта для контроля доступа к нему.
Близнец (Twin). Позволяет моделировать множественное наследование в языках программирования, которые не поддерживают эту функцию.
Поведенческие паттерны (Behavioral patterns)
Черная доска (Blackboard). Паттерн искусственного интеллекта для объединения разрозненных источников данных.
Цепочка ответственности (Chain of responsibility). Избегает привязки отправителя запроса к получателю, предоставляя более чем одному объекту возможность обработать запрос. Сцепляет полученные объекты и передает запрос по цепочке, пока объект не обработает его.
Команда (Command). Инкапсулирует запрос как объект, что позволяет параметризовать клиентов с различными запросами, а также ставить в очередь или регистрировать запросы. Это также позволяет поддерживать отмену операций.
Интерпретатор (Interpreter). Для данного языка определяет представление для его грамматики вместе с интерпретатором, который использует представление для интерпретации предложений на языке.
Итератор (Iterator). Предоставляет способ последовательного доступа к элементам агрегатного объекта без раскрытия его базового представления.
Посредник (Mediator). Определяет объект, который инкапсулирует, как взаимодействует набор объектов. Посредник способствует слабой связанности (loose coupling), не позволяя объектам явно ссылаться друг на друга, и позволяет их взаимодействию изменяться независимо.
Памятка (Memento). Не нарушая инкапсуляцию, захватывает и экстернализует внутреннее состояние объекта, позволяя объекту впоследствии быть восстановленным до этого состояния.
Пустой объект (Null object). Избегает пустых ссылок, предоставляя объект по умолчанию.
Наблюдатель (Observer) или Публикация/подписка (Publish/subscribe). Определяет зависимость "один ко многим" между объектами, при которой изменение состояния одного объекта приводит к тому, что все его зависимые объекты уведомляются и обновляются автоматически.
Слуга (Servant). Определяет общие функциональные возможности для группы классов. Паттерн слуга также часто называют реализацией вспомогательного класса или служебного класса для данного набора классов. Вспомогательные классы обычно не имеют объектов, поэтому у них есть все статические методы, которые воздействуют на различные типы объектов класса.
Спецификация (Specification). Рекомбинируемая бизнес-логика в логическом виде.
Состояние (State). Позволяет объекту изменять свое поведение при изменении его внутреннего состояния. Объект появится, чтобы изменить свой класс.
Стратегия (Strategy). Определяет семейство алгоритмов, инкапсулирует каждый и сделает их взаимозаменяемыми. Стратегия позволяет алгоритму варьироваться независимо от клиентов, которые его используют.
Шаблонный метод (Template method). Определяет каркас алгоритма в операции, отложив некоторые шаги до подклассов. Шаблонный метод позволяет подклассам переопределять определенные этапы алгоритма без изменения структуры алгоритма.
Посетитель (Visitor). Представляет операцию, выполняемую с элементами структуры объекта. Посетитель позволяет определить новую операцию без изменения классов элементов, с которыми он работает.
Паттерны конкурентности (Concurrency patterns)
Активный объект (Active Object). Отделяет выполнение метода от вызова метода, который находится в своем собственном потоке управления. Цель состоит в том, чтобы ввести конкурентность, используя асинхронный вызов метода и планировщик для обработки запросов.
Balking. Выполняет действие над объектом только тогда, когда объект находится в определенном состоянии.
Связывание свойств (Binding properties). Объединение нескольких наблюдателей для принудительной синхронизации или координации свойств в различных объектах.
Вычислительное ядро (Compute kernel). Выполняет одно и то же вычисление много раз параллельно, отличаясь целочисленными параметрами, используемыми с математикой указателя без ветвления в разделяемых массивах, таких как оптимизированное для GPU умножение матриц или сверточная нейронная сеть.
Блокировка с двойной проверкой (Double-checked locking). Сокращает накладные расходы на получение блокировки, сначала проверив критерий блокировки ("подсказка блокировки" (lock hint)) небезопасным способом; только в случае успеха действительная логика блокировки будет продолжаться. Может быть небезопасно, если реализовано в некоторых сочетаниях языка и оборудования. Поэтому иногда это можно считать анти-паттерном.
Основанный на событиях асинхронный (Event-based asynchronous). Решает проблемы с асинхронным паттерном, которые происходят в многопоточных программах.
Защищенная приостановка (Guarded suspension). Управляет операциями, которые требуют как блокировки, так и предварительного условия, которое должно быть выполнено, прежде чем операция может быть выполнена.
Соединение (Join). Предоставляет возможность писать конкурентные, параллельные и распределенные программы путем передачи сообщений. По сравнению с использованием потоков и блокировок, это модель программирования высокого уровня.
Блокировка (Lock). Один поток устанавливает "блокировку" ресурса, не позволяя другим потокам обращаться к нему или изменять его.
Паттерн дизайна обмена сообщениями (Messaging design pattern, MDP). Позволяет обмениваться информацией (т.е. сообщениями) между компонентами и приложениями.
Объект монитора (Monitor object). Объект, методы которого подлежат взаимному исключению, что предотвращает ошибочную попытку его одновременного использования несколькими объектами.
Реактор (Reactor). Реакторный объект обеспечивает асинхронный интерфейс с ресурсами, которые должны обрабатываться синхронно.
Блокировка чтения-записи (Read-write lock). Разрешает одновременный доступ для чтения к объекту, но требует монопольного доступа для операций записи.
Планировщик (Scheduler). Явно контролирует, когда потоки могут выполнять однопоточный код.
Пул потоков (Thread pool). Ряд потоков создается для выполнения ряда задач, которые обычно организованы в очередь. Обычно задач гораздо больше, чем потоков. Можно рассматривать как частный случай паттерна пула объектов.
Хранилище, специфичное для потока (Thread-specific storage). Статическая или "глобальная" память, локальная для потока.
Читайте также:
Комментарии
Отправить комментарий