Составной узор - Composite pattern

В программная инженерия, то составной узор это разбиение шаблон дизайна. Составной шаблон описывает группу объектов, которые обрабатываются так же, как один экземпляр одного и того же типа объекта. Назначение композиции состоит в том, чтобы «составить» объекты в древовидные структуры для представления иерархий «часть-целое». Реализация составного шаблона позволяет клиентам одинаково обрабатывать отдельные объекты и композиции.[1]

Обзор

Композитный[2]шаблон дизайна - один из двадцати трех хорошо известных Шаблоны проектирования GoF в которых описывается, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче реализовать, изменить, протестировать и повторно использовать.

Какие проблемы может решить шаблон проектирования Composite?[3]

  • Должна быть представлена ​​иерархия «часть-целое», чтобы клиенты могли одинаково обращаться с частями и целыми объектами.
  • Иерархия частично и полностью должна быть представлена ​​в виде древовидной структуры.

При определении (1) Часть объекты и (2) Все объекты, которые действуют как контейнеры для Часть объекты, клиенты должны обрабатывать их отдельно, что усложняет клиентский код.

Какое решение описывает шаблон проектирования Composite?

  • Определите единый Составная часть интерфейс для обеих частей (Лист) объекты и целые (Композитный) объекты.
  • Физическое лицо Лист объекты реализуют Составная часть интерфейс напрямую, и Композитный объекты пересылают запросы своим дочерним компонентам.

Это позволяет клиентам работать с Составная часть интерфейс для лечения Лист и Композитный объекты равномерно:Лист объекты выполняют запрос напрямую, и Композитный объекты рекурсивно пересылают запрос своим дочерним компонентам вниз по древовидной структуре, что упрощает реализацию, изменение, тестирование и повторное использование клиентских классов.

См. Также схему классов и объектов UML ниже.

Мотивация

При работе с данными с древовидной структурой программистам часто приходится различать листовой узел и ветвь. Это делает код более сложным и, следовательно, более подверженным ошибкам. Решение представляет собой интерфейс, позволяющий одинаково работать со сложными и примитивными объектами. В объектно-ориентированного программирования, композит - это объект, спроектированный как композиция из одного или нескольких похожих объектов, каждый из которых обладает схожей функциональностью. Это известно как "имеет «отношения между объектами.[4] Ключевая концепция заключается в том, что вы можете манипулировать одним экземпляром объекта так же, как вы бы манипулировали их группой. Операции, которые вы можете выполнять со всеми составными объектами, часто имеют наименьший общий знаменатель отношения. Например, при определении системы для изображения сгруппированных фигур на экране было бы полезно определить изменение размера группы фигур, чтобы иметь тот же эффект (в некотором смысле), что и изменение размера одной фигуры.

Когда использовать

Composite следует использовать, когда клиенты игнорируют разницу между составами объектов и отдельными объектами.[1] Если программисты обнаруживают, что они используют несколько объектов одинаково и часто имеют почти идентичный код для обработки каждого из них, то составной вариант - хороший выбор; в этой ситуации менее сложно рассматривать примитивы и композиты как однородные.

Структура

Диаграмма классов и объектов UML

Пример класса UML и диаграммы объектов для шаблона проектирования Composite. [5]

В приведенном выше UML диаграмма классов, то Клиент класс не относится к Лист и Композитный классы напрямую (по отдельности). Клиент относится к общим Составная часть интерфейс и может лечить Лист и Композитный равномерно.
В Лист класс не имеет потомков и реализует Составная часть интерфейс напрямую.
В Композитный класс поддерживает контейнер дочерних элементовСоставная часть объекты (дети) и пересылает запросы этим дети (для каждого ребенка в children: child.operation ()).

Диаграмма взаимодействия объектов показывает взаимодействия во время выполнения: в этом примере Клиент объект отправляет запрос на верхний уровень Композитный объект (типа Составная часть) в древовидной структуре. Запрос перенаправляется (выполняется) всем дочерним Составная часть объекты (Лист и Композитный объектов) вниз по древовидной структуре.

Определение дочерних операций
Определение дочерних операций в шаблоне проектирования Composite. [6]

Существует два варианта дизайна для определения и реализации операций, связанных с дочерними элементами, таких как добавление / удаление дочернего компонента в / из контейнера (добавить (ребенок) / удалить (ребенок)) и доступ к дочернему компоненту (getChild ()):

  • Дизайн для единообразия: Операции, связанные с дочерними элементами, определены в Составная часть интерфейс. Это позволяет клиентам лечить Лист и Композитный объекты равномерно. Но безопасность типа теряется, потому что клиенты могут выполнять дочерние операции на Лист объекты.
  • Дизайн для обеспечения безопасности типов: Дочерние операции определены только в Композитный класс. Клиенты должны лечить Лист и Композитный объекты по-разному. Но безопасность типов достигается, потому что клиенты могут не выполнять дочерние операции над Лист объекты.

Шаблон дизайна Composite подчеркивает единообразие над безопасность типа.

Диаграмма классов UML

Составной узор в UML.
Составная часть
  • это абстракция для всех компонентов, включая составные
  • объявляет интерфейс для объектов в композиции
  • (необязательно) определяет интерфейс для доступа к родительскому компоненту в рекурсивной структуре и реализует его, если это необходимо
Лист
  • представляет листовые объекты в композиции
  • реализует все методы Component
Композитный
  • представляет собой составной компонент (компонент, имеющий дочерние элементы)
  • реализует методы для управления детьми
  • реализует все методы Component, как правило, делегируя их своим потомкам
Составной узор в LePUS3.

Вариация

Как описано в Шаблоны проектирования, шаблон также включает в себя включение методов управления дочерними элементами в основной интерфейс компонента, а не только в подкласс Composite. В более поздних описаниях эти методы иногда отсутствуют.[7]

пример

Следующий пример, написанный на Ява, реализует графический класс, который может быть либо эллипсом, либо композицией из нескольких графических объектов. Каждый рисунок можно распечатать. В Форма Бэкуса-Наура,

       Графика :: = эллипс | GraphicList GraphicList :: = пусто | Graphic GraphicList

Его можно расширить для реализации нескольких других форм (прямоугольник и т. Д.) И методов (перевести, так далее.).

Ява

импорт java.util.ArrayList;/** "Компонент" */интерфейс Графический {    // Печатает графику.    общественный пустота Распечатать();}/ ** «Составной» * /класс КомпозитныйГрафический орудия Графический {    // Сборник дочерней графики.    частный окончательный ArrayList<Графический> ребенокГрафика = новый ArrayList<>();    // Добавляет графику в композицию.    общественный пустота Добавить(Графический графический) {        ребенокГрафика.Добавить(графический);    }        // Печатает графику.    @Override    общественный пустота Распечатать() {        для (Графический графический : ребенокГрафика) {            графический.Распечатать();  //Делегация        }    }}/** "Лист" */класс Эллипс орудия Графический {    // Печатает графику.    @Override    общественный пустота Распечатать() {        Система.вне.println("Эллипс");    }}/ ** Клиент * /класс CompositeDemo {    общественный статический пустота основной(Строка[] аргументы) {        // Инициализируем четыре эллипса        Эллипс эллипс1 = новый Эллипс();        Эллипс эллипс2 = новый Эллипс();        Эллипс эллипс3 = новый Эллипс();        Эллипс эллипс4 = новый Эллипс();        // Создание двух композитов, содержащих эллипсы        КомпозитныйГрафический графический2 = новый КомпозитныйГрафический();        графический2.Добавить(эллипс1);        графический2.Добавить(эллипс2);        графический2.Добавить(эллипс3);                КомпозитныйГрафический графический3 = новый КомпозитныйГрафический();        графический3.Добавить(эллипс4);                // Создаем еще одну графику, содержащую две графики        КомпозитныйГрафический графический1 = новый КомпозитныйГрафический();        графический1.Добавить(графический2);        графический1.Добавить(графический3);        // Печатает всю графику (в четыре раза больше строки "Ellipse").        графический1.Распечатать();    }}

Смотрите также

использованная литература

  1. ^ а б Гамма, Эрих; Ричард Хелм; Ральф Джонсон; Джон М. Влиссидес (1995). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон-Уэсли. стр.395. ISBN  0-201-63361-2.
  2. ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон Уэсли. стр.163ff. ISBN  0-201-63361-2.CS1 maint: несколько имен: список авторов (ссылка на сайт)
  3. ^ «Шаблон составного дизайна - проблема, решение и применимость». w3sDesign.com. Получено 2017-08-12.
  4. ^ Скотт Уолтерс (2004). Книга шаблонов дизайна Perl. Архивировано из оригинал на 2016-03-08. Получено 2010-01-18.
  5. ^ «Шаблон составного дизайна - структура и взаимодействие». w3sDesign.com. Получено 2017-08-12.
  6. ^ «Шаблон составного проектирования - Реализация». w3sDesign.com. Получено 2017-08-12.
  7. ^ Гири, Дэвид (13 сентября 2002 г.). «Взгляните на шаблон проектирования Composite». Шаблоны проектирования Java. JavaWorld. Получено 2020-07-20.

внешние ссылки