In this article of Java design pattern, we will look at composite design pattern. Composite pattern is one of the structural design pattern. We will take a closer look at the composite design pattern and its various characteristics.
1. What is Composite Design Pattern?
As we said earlier, it’s a part of the structural design pattern. The composite design pattern helps us compose or create an object in to tree structure. The tree structure will help us represent the object in part-whole hierarchy. There are 2 main parts of the composite design pattern.
- Leaf.
- Composite
Let’s try to get some more clarity about these components.
1.1. Leaf.
A leaf is a part with no children. Remember, the composite pattern is a tree structure that represents objects..
1.2. Composite.
Think of composite as a component which can have other components as tree. It’s not the leaf node of the tree.
All of us buy some items online through Amazon or some other eCommerce sites. Let’s take a simple example of the products
that we buy online through these sites. Each product belongs to a certain category
(e.g. electronics or kitchen etc.). A category
can contain several products
. Also within the category
, we can have sub-categories
(e.g. phone with in the electronics) and each sub-category
can also contain some products
.
2. When to Use Composite Design Pattern?
While using the design patterns, we should be clear when to use a design pattern. We developed every design pattern to handle a specific design goals and composite pattern is not different from this. This design pattern is really useful when we need to represent an object in a part-whole hierarchy. Here are some use cases:
- Organization hierarchy chart where each employee is an object.
- Directory structure.
- Menu System.
- File system (like your computer file system)
3. Composite Design Pattern in Java
Let’s build an example of the composite pattern using Java as programming language. We will take an example of the Product
and ProductCategory
for this example, but before we dive in to the example, let’s look at some of the core components.
- All parts of the composition must perform the actions specified in the component interface.. It can be an interface or an abstract class.
- Leaf: A leaf object is an object that does not have any children. It implements the component interface.
- Composite: A composite object is an object that has child objects. It also implements the component interface.
- Client: The client is the code that uses the composite pattern. It does not need to know whether an object is a leaf or a composite.
3.1. Component interface.
package com.javadevjournal.designpatterns.composite;
public interface ProductComponent {
void displayInfo();
}
3.2 Leaf Class
package com.javadevjournal.designpatterns.composite;
// Leaf class
public class Product implements ProductComponent {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public void displayInfo() {
System.out.println("Product: " + name + ", Price: $" + price);
}
}
3.3. Composite Class.
package com.javadevjournal.designpatterns.composite;
import java.util.ArrayList;
import java.util.List;
// Composite class
class ProductCategory implements ProductComponent {
private String categoryName;
private List<ProductComponent> products = new ArrayList<>();
public ProductCategory(String categoryName) {
this.categoryName = categoryName;
}
public void addProduct(ProductComponent product) {
products.add(product);
}
@Override
public void displayInfo() {
System.out.println("Category: " + categoryName);
for (ProductComponent product : products) {
product.displayInfo();
}
}
}
The last part is the client application, which will run the program:
package com.javadevjournal.designpatterns.composite;
public class CompositePatternExample {
public static void main(String[] args) {
// Create individual products
Product product1 = new Product("Product A", 10.0);
Product product2 = new Product("Product B", 20.0);
// Create a product category and add products to it
ProductCategory category1 = new ProductCategory("Category 1");
category1.addProduct(product1);
category1.addProduct(product2);
// Create another individual product
Product product3 = new Product("Product C", 15.0);
// Create another product category and add products to it
ProductCategory category2 = new ProductCategory("Category 2");
category2.addProduct(product3);
category2.addProduct(category1); // Adding a category to a category
// Display information using the composite structure
System.out.println("Displaying products:");
category2.displayInfo();
}
}
3.4. Output.
Once we run this application, we will see the following output:
Displaying products:
Category: Category 2
Product: Product C, Price: $15.0
Category: Category 1
Product: Product A, Price: $10.0
Product: Product B, Price: $20.0
4. Benefits
There are many benefits while using the composite design pattern. Let’s look at a few of them:
- Represent a part-whole hierarchy of objects in a simple and elegant way.
- Adding object to hierarchy is easier. The organization chart makes it easy to add new employees based on their job title. You just have to find the right spot on the chart..
- The composite pattern makes it easy to maintain the code because it reduces the number of conditional statements.
- Simplifies the code for manipulating a complex object hierarchy.
Summary
In this article, we learned about the composite design pattern. The composite pattern is a powerful pattern when we have to represent the complex structure hierarchically. This pattern makes it easy to add / remove element from the structure with minor changes. As always, the source code for this article is available on our GitHub Repository.