Статьи

Составной шаблон дизайна в Java

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

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

Представление 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, являются их собственными.