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. |