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

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

UML-представление составного шаблона выглядит следующим образом:
Куда:
- Компонент: это либо интерфейс, либо абстрактный класс, который является супертипом для всего набора классов.
- Составной класс: он определяет конкретную реализацию Компонента и содержит экземпляры других дочерних компонентов.
- Класс листа: лист представляет собой несоставной тип, т.е. он не состоит из других компонентов
Обратите внимание, что составной объект может содержать другие составные объекты, и это часто называют рекурсивной композицией.
Кроме того, оба класса Leaf и Composite реализуют (расширяют, если это абстрактный класс) интерфейс Component . Это позволяет нам иметь дело с составными и несоставными объектами равномерно посредством полиморфизма.
Лист и составные объекты соответствуют набору общих поведений, определенных в Компоненте .
Реализация составного шаблона:
Давайте построим иерархию меню пользовательского интерфейса, где каждое меню может иметь подменю. Мы будем использовать шаблон составного проекта для реализации этой иерархической структуры.
Для начала давайте определим наш класс MenuComponent :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public abstract class MenuComponent { private String name; private String url; //constructor, getters, setters public void add(MenuComponent component) { throw new UnsupportedOperationException(); } public abstract void displayMenu(); } |
Мы хотим, чтобы агрегированное меню и отдельные элементы меню обрабатывались единообразно, поэтому мы абстрагировали метод displayMenu () в нашем классе MenuComponent .
Давайте теперь реализуем наш класс MenuItem :
|
01
02
03
04
05
06
07
08
09
10
11
|
public class MenuItem extends MenuComponent { public MenuItem(String name, String url) { super(name, url); } @Override public void displayMenu() { System.out.println(getName() + " : " + getUrl()); } } |
Элемент MenuItem будет конечным элементом и не может содержать никаких подменю.
Меню , с другой стороны, состоит из объектов MenuComponent . Другими словами, Меню может содержать объекты Menu и MenuItem :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public class Menu extends MenuComponent { List<MenuComponent> subMenus = new ArrayList<>(); public Menu(String name, String url) { super(name, url); } @Override public void add(MenuComponent menuComponent) { this.subMenus.add(menuComponent); } @Override public void displayMenu() { System.out.println(getName() + " : " + getUrl() + "\n"); this.subMenus.forEach(MenuComponent::displayMenu); }} |
Тестирование нашей реализации:
Ожидается, что клиентский код будет работать с абстракцией MenuComponent . Давайте создадим иерархию пунктов меню:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
MenuComponent allTutorials = new Menu("Tutorials", "/tutorials"); MenuComponent spring = new Menu("Spring", "/spring");MenuComponent versioning = new Menu("Version Management", "/versioning"); MenuComponent java = new MenuItem("Java", "/java"); allTutorials.add(spring);allTutorials.add(versioning);allTutorials.add(java); spring.add(new MenuItem("Spring Core", "/core"));spring.add(new MenuItem("Spring Boot", "/boot")); MenuComponent git = new Menu("Git", "/git"); MenuComponent svn = new MenuItem("SVN", "/svn"); versioning.add(svn);versioning.add(git); git.add(new MenuItem("Introduction to Git", "/intro"));git.add(new MenuItem("Github Integration", "/github")); allTutorials.displayMenu(); |
Приведенный выше код даст следующий вывод:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
Tutorials:/tutorials Spring:/spring Spring Core : /coreSpring Boot : /boot Version Management:/versioning SVN : /svnGit:/git Introduction to Git : /introGithub Integration : /github Java : /java |
Вывод:
В этом уроке мы рассмотрели шаблон составного дизайна. Это структурный паттерн, который пригодится при попытке создать иерархическую структуру объектов. Это помогает нам одинаково относиться к сложным и несоставным объектам.
|
Опубликовано на Java Code Geeks с разрешения Шубхры Шриваставы, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Составной шаблон проектирования в Java Мнения, высказанные участниками Java Code Geeks, являются их собственными. |