Введение в шаблоны проектирования, Часть 1: История и классификация шаблонов проектирования

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

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

Что такое шаблон проектирования?

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

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

« Шаблон проектирования описывает классы и взаимодействующие объекты, используемые для решения общей проблемы проектирования в определенном контексте».

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

  1. Имя , которое описывает шаблон проектирования и дает нам словарь для обсуждения его
  2. Проблема , которая определяет проблему конструкции , требующие , чтобы быть решена вместе с контекстом , в котором возникает проблема
  3. Решение проблемы, которое (в контексте шаблона проектирования программного обеспечения) следует определить классы и объекты , которые вносят вклад в дизайн наряду с их отношениями и другими факторами
  4. Объяснение последствий использования шаблона проектирования

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

Оценка шаблона проектирования

Рассмотрим задачу разработки сложного пользовательского интерфейса с использованием кнопок, текстовых полей и других неконтейнерных компонентов. Шаблон проектирования Composite рассматривает контейнеры как компоненты, что позволяет нам вкладывать контейнеры и их компоненты (контейнеры и неконтейнеры) в другие контейнеры и делать это рекурсивно. Если бы мы решили не использовать шаблон Composite, нам пришлось бы создать множество специализированных неконтейнерных компонентов (например, один компонент, объединяющий текстовое поле пароля и кнопку входа в систему), чего труднее достичь.

Поразмыслив над этим, мы понимаем проблему, которую пытаемся решить, и решение, предлагаемое шаблоном Composite. Но каковы последствия использования этого шаблона?

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

Что не так с проверками типов во время выполнения?

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

Также возможно выбрать подходящий шаблон проектирования и использовать его неправильно. Блокировки с двойной проверкой шаблоном является классическим примером. Блокировка с двойной проверкой сокращает накладные расходы на получение блокировки, сначала проверяя критерий блокировки без фактического получения блокировки, а затем приобретая блокировку только в том случае, если проверка указывает, что блокировка требуется. Хотя на бумаге это выглядело хорошо, блокировка с двойной проверкой в ​​JDK 1.4 имела некоторые скрытые сложности. Когда JDK 5 расширил семантику volatileключевого слова, разработчики наконец смогли воспользоваться преимуществами шаблона блокировки с двойной проверкой.

Подробнее о блокировке с двойной проверкой

См. Разделы «Блокировка с двойной проверкой: умно, но не работает» и «Можно ли исправить блокировку с двойной проверкой?» (Брайан Гетц, JavaWorld), чтобы узнать больше о том, почему этот шаблон не работал в JDK 1.4 и ранее. Для получения дополнительных сведений об указании DCL в JDK 5 и более поздних версиях см. «Декларация« Двойная проверка блокировки не работает »» (Департамент компьютерных наук Мэрилендского университета, Дэвид Бэкон и др.).

Анти-паттерны

Когда шаблон проектирования обычно используется, но является неэффективным и / или контрпродуктивным, шаблон проектирования называется анти-шаблоном . Кто-то может возразить, что блокировка с двойной проверкой, используемая в JDK 1.4 и ранее, была анти-шаблоном. Я бы сказал, что в этом контексте это была просто плохая идея. Чтобы плохая идея превратилась в антипаттерн, должны быть выполнены следующие условия (см. Ресурсы).

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

Хотя блокировка с двойной проверкой в ​​JDK 1.4 действительно соответствовала первому требованию анти-шаблона, она не соответствовала второму: хотя вы могли бы использовать synchronizedдля решения проблемы ленивой инициализации в многопоточной среде, выполнение этого позволило бы устранить причину возникновения используя в первую очередь блокировку с двойной проверкой.

Антипаттерны тупиков

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

  • Нет арбитража
  • Агрегация рабочих
  • Инкрементальная блокировка

История паттернов проектирования

Шаблоны проектирования появились в конце 1970-х, когда была опубликована книга «Язык шаблонов: города, здания, строительство » архитектора Кристофера Александра и некоторых других. Эта книга представила шаблоны проектирования в архитектурном контексте, представив 253 шаблона, которые в совокупности сформировали то, что авторы назвали языком шаблонов .

Ирония паттернов проектирования

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

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

Тем временем Кент Бек и Уорд Каннингем начали изучать шаблоны и их применимость в разработке программного обеспечения. В 1987 году они использовали серию шаблонов проектирования, чтобы помочь группе Tektronix Semiconductor Test Systems Group, у которой возникли проблемы с завершением дизайн-проекта. Бек и Каннингем последовали совету Александра в отношении дизайна, ориентированного на пользователя (позволяя представителям пользователей проекта определять результат дизайна), а также предоставили им некоторые шаблоны проектирования, облегчающие работу.

Эрих Гамма также осознал важность повторяющихся шаблонов проектирования во время работы над своей докторской диссертацией. Он считал, что шаблоны проектирования могут облегчить задачу написания объектно-ориентированного программного обеспечения многократного использования, и размышлял о том, как их эффективно документировать и передавать. До Европейской конференции по объектно-ориентированному программированию 1991 года Гамма и Ричард Хелм начали каталогизировать шаблоны.

На семинаре OOPSLA, проведенном в 1991 году, к Гамме и Хелму присоединились Ральф Джонсон и Джон Влиссидес. Эта банда четырех (GoF), как они впоследствии стали называть, написала популярные шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования , в которых задокументировано 23 шаблона проектирования в трех категориях.

Современная эволюция шаблонов проектирования

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

В 1994 году некоммерческая организация, расположенная в США, известная как Hillside Group, открыла программу «Языки шаблонов» - группу ежегодных конференций, целью которых является развитие и совершенствование искусства шаблонов проектирования программного обеспечения. Эти продолжающиеся конференции дали множество примеров шаблонов проектирования для конкретных предметных областей. Например, шаблоны проектирования в контексте параллелизма.

Кристофер Александр в OOPSLA

С программной речью OOPSLA 96 выступил архитектор Кристофер Александр. Александр рассказал о своей работе и о том, как сообщество объектно-ориентированного программирования попало в цель и упустило его, приняв и адаптировав его идеи о языках шаблонов в программном обеспечении. Вы можете прочитать обращение Александра полностью: «Истоки теории паттернов: будущее теории и создание живого мира».

В 1998 году Марк Гранд выпустил « Шаблоны на Java» . В эту книгу включены шаблоны проектирования, которых нет в книге GoF, включая шаблоны параллелизма. Grand также использовал унифицированный язык моделирования (UML) для описания шаблонов проектирования и их решений. Примеры книги были выражены и описаны на языке Java.

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

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

Другие типы шаблонов проектирования

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

Шаблоны создания

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

  • Абстрактная фабрика : этот шаблон предоставляет интерфейс для инкапсуляции группы отдельных фабрик, имеющих общую тему, без указания их конкретных классов.
  • Строитель : отделяет построение сложного объекта от его представления, позволяя одному и тому же процессу построения создавать различные представления. Абстрагирование шагов построения объекта позволяет различным реализациям шагов конструировать различные представления объектов.
  • Заводской метод : определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс создать. Этот шаблон позволяет классу отложить создание экземпляра до подклассов. Внедрение зависимостей - это связанный шаблон. (См. Ресурсы.)
  • Ленивая инициализация : этот шаблон дает нам возможность отложить создание объекта, поиск в базе данных или другой дорогостоящий процесс до первого раза, когда потребуется результат.
  • Multiton : расширяет концепцию синглтона для управления картой именованных экземпляров класса как пар ключ-значение и обеспечивает глобальную точку доступа к ним.
  • Пул объектов : держите набор инициализированных объектов готовым к использованию, а не выделяйте и уничтожайте по запросу. Цель состоит в том, чтобы избежать дорогостоящего приобретения и утилизации ресурсов за счет повторного использования объектов, которые больше не используются.
  • Прототип : определяет типы объектов, которые необходимо создать, используя прототип, а затем создавать новые объекты, копируя этот прототип. Прототип клонируется для создания новых объектов.
  • Получение ресурсов - это инициализация : этот шаблон обеспечивает автоматическую и правильную инициализацию и восстановление ресурсов путем привязки их к сроку службы подходящих объектов. Ресурсы приобретаются во время инициализации объекта, когда нет шансов, что они будут использованы до того, как они станут доступны, и высвобождаются с уничтожением тех же объектов, что гарантированно произойдет даже в случае ошибок.
  • Синглтон : гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру.