Составной шаблон проектирования полезен, когда нам приходится работать с древовидной иерархической структурой объектов.
Это позволяет нам обрабатывать отдельные объекты и состав объектов равномерно. Он подпадает под категорию структурного шаблона проектирования, поскольку он объединяет объекты в древовидную структуру для представления иерархий части-целого.
Представление 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 : /core Spring Boot : /boot Version Management: /versioning SVN : /svn Git: /git Introduction to Git : /intro Github Integration : /github Java : /java |
Вывод:
В этом уроке мы рассмотрели шаблон составного дизайна. Это структурный паттерн, который пригодится при попытке создать иерархическую структуру объектов. Это помогает нам одинаково относиться к сложным и несоставным объектам.
Опубликовано на Java Code Geeks с разрешения Шубхры Шриваставы, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Составной шаблон проектирования в Java Мнения, высказанные участниками Java Code Geeks, являются их собственными. |