Other Tutorials

Composite Design Pattern In Java

Introduction:

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:Composite Design Pattern

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.

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *