Core Java

Composite Design Pattern In Java

A composite design pattern is useful when we have to work with a tree-like hierarchical structure of objects.

It lets us treat the individual objects and the composition of objects uniformly. It falls under the category of a structural design pattern as it composes objects into a tree structure to represent part-whole hierarchies.

UML Representation:

The UML representation of a composite pattern looks like:

Where:

  • Component: is either an interface or an abstract class which is a supertype for all set of classes
  • Composite class: it defines a concrete implementation of Component and holds instances of other child components
  • Leaf class: A leaf represents a non-composite type i.e. it isn’t composed of other components

Note that a composite object can contain other composite objects and this is often termed as recursive composition.

Additionally, both Leaf and Composite classes implement(extend if an abstract class) the Component interface. This enables us to deal with composite and non-composite objects uniformly through polymorphism.

The leaf and the composite objects conform to a set of shared behaviors defined in Component.

Implementing the Composite Pattern:

Let’s build a UI menu hierarchy where each menu can have sub-menus. We’ll use the composite design pattern to implement this hierarchical structure.

To begin with, let’s define our MenuComponent class:

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();  
}

We want the aggregated menu and the individual menu items to be treated uniformly so we have abstracted out the displayMenu() method in our MenuComponent class.

Let’s now implement our MenuItem class:

public class MenuItem extends MenuComponent {
 
    public MenuItem(String name, String url) {
        super(name, url);
    }
 
    @Override
    public void displayMenu() {
        System.out.println(getName() + " : " + getUrl());
    }       
}

A MenuItem will be the leaf element and can’t hold any submenus.

A Menu, on the other hand, is composed of MenuComponent objects. In other words, a Menu can hold both Menu and MenuItem objects:

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);
    }
}

Testing Our Implementation:

The client code is expected to work with MenuComponent abstraction. Let’s create a hierarchy of menu items:

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();

The above code will produce the following output:

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

Conclusion:

In this tutorial, we explored the composite design pattern. It’s a structural pattern which comes handy when trying to create a hierarchical structure of objects. It helps us to treat the composite and non-composite objects uniformly.

Published on Java Code Geeks with permission by Shubhra Srivastava, partner at our JCG program. See the original article here: Composite Design Pattern In Java

Opinions expressed by Java Code Geeks contributors are their own.

Shubhra Srivastava

Shubhra is a software professional and founder of ProgrammerGirl. She has a great experience with Java/J2EE technologies and frameworks. She loves the amalgam of programming and coffee :)
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button