Шаблоны проектирования

редактировать
Шаблоны проектирования:. Элементы многоразового объектно-ориентированного программного обеспечения
Обложка шаблонов дизайна. jpg
Автор«Банда Четыре »:
СтранаСША
ТемаШаблоны проектирования, разработка программного обеспечения, объектно-ориентированное программирование
PublisherAddison-Wesley
Дата публикации1994
Pages395
ISBN 0-201-63361-2
OCLC 31171684
Десятичное число Дьюи 005.1 / 2 20
Класс LC QA76.64.D47 1995

Шаблоны проектирования: элементы Многоразовое объектно-ориентированное программное обеспечение (1994) - это книга по разработке программного обеспечения, в которой описываются шаблоны проектирования программного обеспечения. Книгу написали Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес, с предисловием Грэди Буч. Книга разделена на две части: первые две главы посвящены возможностям и подводным камням объектно-ориентированного программирования, а остальные главы описывают 23 классических паттерна проектирования программного обеспечения. В книгу включены примеры на C ++ и Smalltalk.

. Он оказал большое влияние на область разработки программного обеспечения и считается важным источником теории и практики объектно-ориентированного проектирования. Было продано более 500 000 копий на английском и 13 других языках. Авторов часто называют «Бандой четырех» (GoF ).

Содержание

  • 1 История
  • 2 Введение
  • 3 Практический пример
    • 3.1 Структура документа
    • 3.2 Форматирование
    • 3.3 Улучшение пользовательского интерфейса
    • 3.4 Поддержка нескольких стандартов внешнего вида
    • 3.5 Поддержка нескольких оконных систем
    • 3.6 Пользовательские операции
    • 3.7 Проверка орфографии и расстановка переносов
  • 4 шаблона по типу
    • 4.1 Творческий
    • 4.2 Структурный
    • 4.3 Поведенческий
  • 5 Критика
  • 6 См. также
  • 7 Примечания
  • 8 Ссылки

История

Книга началось на сеансе птицы пера (BoF) в OOPSLA '90, «На пути к руководству по архитектуре», проведенном Брюсом Андерсоном, где Эрих Гамма и Ричард Хелм встретились и обнаружили их общий интерес. Позже к ним присоединились Ральф Джонсон и Джон Влиссидес. Первоначальной датой публикации книги было 21 октября 1994 года с авторским правом 1995 года, поэтому ее часто цитируют с 1995 годом, несмотря на то, что она была опубликована в 1994 году. был впервые сделан доступный для общественности на собрании OOPSLA, состоявшемся в Портленде, штат Орегон, в октябре 1994 года. В 2005 году ACM SIGPLAN присудил авторам премию за достижения в области языков программирования за тот год в знак признания влияния их работы "на практика программирования и дизайн языков программирования ». По состоянию на март 2012 года книга выходила в 40-й тираж.

Введение

В главе 1 обсуждаются объектно-ориентированные методы проектирования, основанные на опыте авторов, которые, по их мнению, приведут к хорошему объектно-ориентированному дизайну программного обеспечения., включая:

Авторы заявляют о следующих преимуществах интерфейсов по сравнению с реализацией:

  • клиенты не знают о конкретных типах объектов, которые они используют, пока объект придерживается к интерфейсу
  • клиенты остаются в неведении о классах, реализующих эти объекты; клиенты знают только об абстрактном классе (ах), определяющем интерфейс

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

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

Авторы подробно обсуждают противоречие между наследованием и инкапсуляцией и заявляют, что, по их опыту, дизайнеры злоупотребляют наследованием (Gang of Four 1995: 20). Опасность формулируется следующим образом:

«Поскольку наследование раскрывает подкласс деталям реализации его родителя, часто говорят, что« наследование нарушает инкапсуляцию »». (Gang of Four 1995: 19)

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

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

Для авторов «делегирование» - это крайняя форма композиции объектов, которую всегда можно использовать для замены наследования. Делегирование включает в себя два объекта: «отправитель» передает себя «делегату», чтобы позволить делегату обратиться к отправителю. Таким образом, связь между двумя частями системы устанавливается только во время выполнения, а не во время компиляции. В статье Обратный вызов есть дополнительная информация о делегировании.

Авторы также обсуждают так называемые параметризованные типы, которые также известны как обобщенные типы (Ada, Eiffel, Java, C #, VB.NET и Delphi) или шаблоны (C ++). Они позволяют определять любой тип без указания всех других используемых им типов - неуказанные типы предоставляются как «параметры» в момент использования.

Авторы признают, что делегирование и параметризация очень эффективны, но добавляют предупреждение:

«Динамическое программное обеспечение с высокой степенью параметризации труднее понять и построить, чем более статическое программное обеспечение». (Gang of Four 1995: 21)

Далее авторы проводят различие между «Агрегация », где один объект «имеет» или «является частью» другого объекта (подразумевая, что совокупный объект и его владелец имеют идентичные сроки жизни) и знакомство, где один объект просто «знает» другой объект. Иногда знакомство называют отношениями «ассоциации» или «использования». Объекты знакомств могут запрашивать операции друг у друга, но не несут ответственности друг за друга. Знакомство - это более слабая связь, чем агрегирование, и предполагает гораздо более слабую связь между объектами, что часто может быть желательно для максимальной ремонтопригодности проекта.

Авторы используют термин «инструментарий» там, где другие сегодня могут использовать «библиотеку классов», например, в C # или Java. На их языке, инструментальные средства являются объектно-ориентированным эквивалентом библиотек подпрограмм, тогда как «framework » - это набор взаимодействующих классов, которые составляют повторно используемый дизайн для определенного класса программного обеспечения. Они заявляют, что приложения сложно спроектировать, инструментарий сложнее, а фреймворки сложнее всего разработать.

Практический пример

Глава 2 представляет собой пошаговое тематическое исследование «дизайна» What-You-See-Is-What-You-Get '(или' WYSIWYG ') редактор документов под названием Lexi. " (стр. 33)

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

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

Ниже перечислены семь проблем (включая их ограничения) и их решения (включая шаблон (ы)):

Структура документа

Документ является " расположение основных графических элементов, таких как символы, линии, другие формы и т. д., которые «отражают все информационное содержание документа» (стр. 35). Структура документа содержит набор этих элементов, и каждый элемент, в свою очередь, может быть подструктурой других элементов.

Проблемы и ограничения

  1. Текст и графику следует обрабатывать одинаково (то есть, графика не является производным экземпляром текста, и наоборот)
  2. Реализация должна обрабатывать сложные и простые структуры так же. Ему не обязательно знать разницу между ними.
  3. Конкретные производные абстрактных элементов должны иметь специализированные аналитические элементы.

Решение и шаблон

Рекурсивная композиция - это иерархическая структура элементов, которая строит «все более сложные элементы из более простых» (стр. 36). Каждый узел в структуре знает о своих дочерних элементах и ​​своих родителях. Если операция должна быть выполнена для всей структуры, каждый узел вызывает операцию для своих дочерних элементов (рекурсивно).

Это реализация составного шаблона , который представляет собой набор узлов. Узел является абстрактным базовым классом , а производные могут быть либо листьями (единичными), либо коллекциями других узлов (которые, в свою очередь, могут содержать листья или узлы коллекции). Когда операция выполняется над родительским элементом, эта операция рекурсивно передается вниз по иерархии.

Форматирование

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

Проблемы и ограничения

  1. Баланс между качеством (форматированием), скоростью и объемом памяти
  2. Сохранение независимого (несвязанного) форматирования от структура документа.

Решение и шаблон

Класс Compositor инкапсулирует алгоритм, используемый для форматирования композиции. Композитор - это подкласс примитивного объекта структуры документа. Compositor имеет связанный экземпляр объекта Composition. Когда Compositor запускает свой Compose (), он выполняет итерацию по каждому элементу связанной с ним композиции и переупорядочивает структуру, вставляя при необходимости объекты Row и Column.

Compositor сам по себе является абстрактным классом, позволяющим производным классам использовать различные алгоритмы форматирования (такие как двойной интервал, более широкие поля и т. Д.)

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

Украшение пользовательского интерфейса

Возможность изменять графический интерфейс, который пользователь использует для взаимодействия с документом.

Проблемы и ограничения

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

Решение и шаблон

Использование Прозрачный корпус позволяет добавлять в композицию элементы, улучшающие поведение композиции. Эти элементы, такие как Border и Scroller, являются специальными подклассами самого единственного элемента. Это позволяет дополнять композицию, эффективно добавляя элементы, подобные состояниям. Поскольку эти дополнения являются частью структуры, их соответствующая операция Operation ()будет вызываться при вызове структуры Operation (). Это означает, что клиенту не нужны какие-либо специальные знания или взаимодействие со структурой, чтобы использовать украшения.

Это шаблон Decorator, который добавляет обязанности к объекту без изменения самого объекта.

Поддержка нескольких стандартов внешнего вида

Внешний вид относится к стандартам пользовательского интерфейса для платформы. Эти стандарты «определяют правила внешнего вида приложений и их реакции на пользователя» (стр. 47).

Проблемы и ограничения

  1. Редактор должен реализовывать стандарты для нескольких платформ, чтобы он был портативным
  2. Легко адаптироваться к новым и возникающим стандартам
  3. Разрешать изменение внешнего вида во время выполнения- и-чувствовать (например: Нет жесткого кодирования )
  4. Имейте набор абстрактных подклассов элементов для каждой категории элементов (ScrollBar, Buttons и т. д.)
  5. Имейте набор конкретных подклассов для каждого абстрактный подкласс, который может иметь другой стандарт внешнего вида (ScrollBar, имеющий MotifScrollBar и PresentationScrollBar для внешнего вида Motif и Presentation)

Решение и шаблон

Поскольку создание различных конкретных объектов невозможно на во время выполнения процесс создания объекта должен быть абстрагированным. Это делается с помощью абстрактного guiFactory, который берет на себя ответственность за создание элементов пользовательского интерфейса. Абстрактный guiFactory имеет конкретные реализации, такие как MotifFactory, который создает конкретные элементы соответствующего типа (MotifScrollBar). Таким образом, прога ram нужно только запросить ScrollBar, и во время выполнения ему будет предоставлен правильный конкретный элемент.

Это Абстрактная фабрика. Обычная фабрика создает конкретные объекты одного типа. Абстрактная фабрика создает конкретные объекты разных типов в зависимости от конкретной реализации самой фабрики. Его способность фокусироваться не только на конкретных объектах, но и на целых семействах конкретных объектов «отличает его от других творческих паттернов, которые включают только один вид объекта продукта» (стр. 51).

Поддержка многооконных систем

Так же, как внешний вид различается на разных платформах, так же и метод работы с окнами. Каждая платформа отображает, размещает, обрабатывает ввод и вывод, а также по-разному наслоит окна.

Проблемы и ограничения

  1. Редактор документов должен работать на многих существующих «важных и в значительной степени несовместимых оконных системах» (стр. 52)
  2. Абстрактную фабрику использовать нельзя. Из-за различных стандартов не будет общего абстрактного класса для каждого типа виджета.
  3. Не создавайте новую нестандартную оконную систему

Решение и шаблон

Можно разработать "наш собственные абстрактные и конкретные классы продуктов », потому что« все оконные системы обычно делают одно и то же »(стр. 52). Каждая оконная система обеспечивает операции по рисованию примитивных форм, уменьшению / уменьшению значков, изменению размеров и обновлению содержимого окна.

Абстрактный базовый класс Windowможет быть унаследован от различных типов существующих окон, таких как приложение, диалог. Эти классы будут содержать операции, связанные с окнами, такие как изменение формы, графическое обновление и т. Д. Каждое окно содержит элементы, чьи функции Draw ()вызываются объектами Window. собственные функции, связанные с отрисовкой.

Чтобы избежать необходимости создавать зависящие от платформы подклассы Window для каждой возможной платформы, будет использоваться интерфейс. Класс Windowреализует абстрактный класс Window(WindowImp). Этот класс, в свою очередь, будет производным от нескольких реализаций, зависящих от платформы, каждая из которых выполняет операции, зависящие от платформы. Следовательно, только один набор классов Windowнеобходим для каждого типа Window, и только один набор классов WindowImpнеобходим для каждой платформы (а не Декартово произведение всех доступных типов и платформ). Кроме того, добавление нового типа окна не требует каких-либо изменений в реализации платформы и наоборот.

Это Образец моста. Windowи WindowImpразные, но взаимосвязанные. Windowработает с окнами в программе, а WindowImpработает с окнами на платформе. Один из них может измениться, не изменяя другой. Шаблон «Мост» позволяет этим двум «отдельным иерархиям классов работать вместе, даже если они развиваются независимо» (стр. 54).

Действия пользователя

Все действия, которые пользователь может выполнять с документом, начиная от ввода текста, изменения форматирования, выхода, сохранения и т. Д.

Проблемы и ограничения

  1. Операции должны быть доступ к ним осуществляется через разные входы, такие как пункт меню и сочетание клавиш для одной и той же команды
  2. Каждый параметр имеет интерфейс, который должен быть изменяемым
  3. Операции реализованы в нескольких разных классах
  4. Во избежание связи между реализацией и классами пользовательского интерфейса не должно быть много зависимостей.
  5. Команды отмены и повтора должны поддерживаться в большинстве операций изменения документа, при без произвольного ограничения по количеству уровней отмены
  6. Функции нежизнеспособны, поскольку их нелегко отменить / повторить, их нелегко связать с состоянием и их сложно расширить или повторно использовать.
  7. Меню следует рассматривать как иерархические составные структуры. Следовательно, меню - это пункт меню, который содержит пункты меню, которые могут содержать другие пункты меню и т. Д.

Решение и шаблон

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

Команда - это абстрактный объект, который имеет только один абстрактный метод Execute (). Производные объекты расширяют метод Execute ()соответствующим образом (т.е. PasteCommand.Execute ()будет использовать буфер буфера обмена содержимого). Эти объекты могут использоваться виджетами или кнопками так же легко, как и элементами меню.

Для поддержки отмены и повтора командетакже даны Unexecute ()и Reversible (). В производных классах первый содержит код, который отменяет эту команду, а второй возвращает логическое значение, которое определяет, нельзя ли выполнить команду. Reversible ()позволяет не отменять некоторые команды, например команду «Сохранить».

Все выполненные Командыхранятся в списке с методом сохранения маркера «присутствия» сразу после последней выполненной команды. Запрос на отмену вызовет Command.Unexecute ()непосредственно перед словом «присутствует», а затем переместит «присутствует» на одну команду назад. И наоборот, запрос Redoвызовет Command.Execute ()после «присутствует» и переместит «настоящее» вперед.

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

Проверка орфографии и расстановка переносов

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

Проблемы и ограничения

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

Решение и шаблон

Удаление целочисленного индекса из базового элемента позволяет реализовать другой интерфейс итерации. Это потребует дополнительных методов для обхода и поиска объекта. Эти методы помещены в абстрактный интерфейс Iterator. Затем каждый элемент реализует производное от Iterator, в зависимости от того, как этот элемент хранит свой список (ArrayIterator, LinkListIteratorи т. Д.).

Функции обхода и поиска помещены в абстрактный интерфейс Iterator. Будущие итераторы могут быть получены на основе типа списка, который они будут повторять, например, массивы или связанные списки. Таким образом, независимо от того, какой метод индексации использует любая реализация элемента, у нее будет соответствующий итератор.

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

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

Вместо этого общий метод CheckMe ()встроен в абстрактный класс элемента. Каждому итератору дается ссылка на определенный алгоритм (например, проверка орфографии, проверка грамматики и т. Д.). Когда этот итератор выполняет итерацию по своей коллекции, он вызывает каждый элемент CheckMe, передавая указанный алгоритм. CheckMeзатем передает ссылку на свой элемент обратно в упомянутый алгоритм для анализа.

Таким образом, для выполнения проверки орфографии интерфейсному итератору будет дана ссылка на объект SpellCheck. Затем итератор обращается к каждому элементу, выполняя свой метод CheckMe ()с параметром SpellCheck. Каждый CheckMeзатем будет вызывать SpellCheck, передавая ссылку на соответствующий элемент.

Таким образом, любой алгоритм может использоваться с любым методом обхода без жесткой привязки одного кода к другому. Например, Find может использоваться как «найти следующий» или «найти предыдущий», в зависимости от того, использовался ли итератор «вперед» или итератор «назад».

Кроме того, сами алгоритмы могут отвечать за работу с различными элементами. Например, алгоритм SpellCheckбудет игнорировать элемент Graphic, вместо того, чтобы программировать каждый элемент, производный от Graphic, чтобы не отправлять себя в SpellCheck.

Шаблоны по типу

Создание

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

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

Структурный

Они касаются композиции классов и объектов. Они используют наследование для компоновки интерфейсов и определения способов компоновки объектов для получения новой функциональности.

  • Адаптер позволяет классам с несовместимыми интерфейсами работать вместе, оборачивая свой собственный интерфейс вокруг интерфейса уже существующего класса.
  • Мост отделяет абстракцию от ее реализации, так что они могут различаться независимо.
  • Composite составляет ноль или более похожих объектов, так что ими можно управлять как одним объектом.
  • Decorator динамически добавляет / отменяет поведение в существующем методе объекта.
  • Facade предоставляет упрощенный интерфейс к большому объему кода.
  • Flyweight снижает затраты на создание и управление большим количеством похожих объектов.
  • Прокси предоставляет заполнитель для другого объекта для управления доступом, снизить стоимость и уменьшить сложность.

Поведенческие

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

  • Цепочка ответственности делегирует команды цепочке обрабатывающих объектов.
  • Команда создает объекты, которые инкапсулируют действия и параметры ters.
  • Интерпретатор реализует специализированный язык.
  • Итератор последовательно обращается к элементам объекта, не раскрывая его базовое представление.
  • Посредник допускает слабую связь между классами, будучи единственным классом, который имеет подробные сведения о своих методах.
  • Memento предоставляет возможность восстановить объект в его предыдущее состояние (отменить).
  • Observer - шаблон публикации / подписки который позволяет нескольким объектам-наблюдателям видеть событие.
  • Состояние позволяет объекту изменять свое поведение при изменении его внутреннего состояния.
  • Стратегия позволяет выбрать один из семейства алгоритмов на -the-fly во время выполнения.
  • Шаблонный метод определяет скелет алгоритма как абстрактный класс, позволяя его подклассам обеспечивать конкретное поведение.
  • Посетитель отделяет алгоритм от структуры объекта путем перемещения иерархия методов в один объект.

Критика

Критика была направлена ​​на концепцию шаблоны проектирования программного обеспечения в целом, и в частности, в шаблонах проектирования. Основная критика шаблонов проектирования заключается в том, что их шаблоны - это просто обходные пути для отсутствующих функций в C ++, заменяющие элегантные абстрактные функции длинными конкретными шаблонами, по сути становясь «человеческим компилятором» или «генерируя вручную расширения некоторых макросов». Питер Норвиг демонстрирует, что 16 из 23 шаблонов в шаблонах проектирования упрощены или устранены (посредством прямой языковой поддержки) в Lisp или Dylan. Связанные с этим наблюдения были сделаны Ханнеманом и Кицалесом, которые реализовали несколько из 23 шаблонов проектирования с использованием аспектно-ориентированного языка программирования (AspectJ ) и показали, что на уровне кода зависимости были удалены из реализаций 17 из 23 шаблонов проектирования, и что аспектно-ориентированное программирование могло упростить реализацию шаблонов проектирования.

Пол Грэм писал:

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

Также была юмористическая критика, такая как показательный процесс на OOPSLA '99 3 ноября 1999 г. и пародия на формат, сделанная Джимом Коплиеном, озаглавленная «Кондиционер Канзас-Сити ".

В интервью InformIT в 2009 году Эрих Гамма заявил, что в 2005 году авторы книги обсуждали, как бы они реорганизовали книгу, и пришли к выводу, что они бы переклассифицировали некоторые шаблоны и добавили несколько дополнительных. Gamma хотела удалить шаблон Singleton, но авторы не достигли консенсуса по этому поводу.

См. Также

Примечания

Ссылки

Последняя правка сделана 2021-05-17 14:50:50
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте