Composite patterns allow clients to treat individual objects (under a hierarchical structure) in a uniform manner.
The composite pattern is most suitable for working with objects that form a tree-like hierarchy. In that tree, each node/object (except the root node) is either a composite or leaf node. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
1. When to use Composite Pattern?
Composite design pattern compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
- When the application has a hierarchical structure and needs generic functionality across the structure.
- When an application needs to aggregate data across a hierarchy.
- When an application wants to treat composite and individual objects uniformly.
Real-life example usage of composite design patterns may be:
- Building consolidated view of a customer’s account in the bank (i.e., customer’s portfolio)
- Building general ledgers
- Computer/network monitoring applications
- Retail and inventory applications
- Directory structure in file system implementations
- Menu items in GUI screens
2. Design Participants
Below are the participants in any composite pattern-based solution.

Where the classes and objects participating in this pattern are:
- Component
- declares the interface for objects in the composition.
- implements default behavior for the interface common to all classes, as appropriate.
- declares an interface for accessing and managing its child components.
- Leaf
- represents leaf objects in the composition. A leaf has no children.
- defines behavior for primitive objects in the composition.
- Composite
- defines behavior for components having children.
- stores child components.
- implements child-related operations in the
Component
interface.
- Client
- manipulates objects in the composition through the
Component
interface.
- manipulates objects in the composition through the
In the above diagram, the client uses the Component
interface to interact with objects in a composite hierarchy. Inside the hierarchy, if an object is composite, it passes the request to leaf nodes. If an object is a leaf node, the request is handled immediately.
Composite leaves also have the choice of modifying the request/response either before or after the leaf node handles it.
3. The Problem
Let’s suppose we are building a financial application. We have customers with multiple bank accounts. We are asked to prepare a design that can help generate the customer’s consolidated account view, which can show the customer’s total account balance and the consolidated account statement after merging all the account statements. So, the application should be able to generate:
4. Implementation
Here, we are dealing with account objects, which form a tree-like structure in which we will traverse and perform some operations on account objects only. Thus, we can apply the composite design pattern.
Let’s see the participating classes:
Component.java
public abstract class Component {
AccountStatement accStatement;
protected List<Component> list = new ArrayList<>();
public abstract float getBalance();
public abstract AccountStatement getStatement();
public void add(Component g) {
list.add(g);
}
public void remove(Component g) {
list.remove(g);
}
public Component getChild(int i) {
return (Component) list.get(i);
}
}
CompositeAccount.java
public class CompositeAccount extends Component {
private float totalBalance;
private AccountStatement compositeStmt, individualStmt;
public float getBalance() {
totalBalance = 0;
for (Component f : list) {
totalBalance = totalBalance + f.getBalance();
}
return totalBalance;
}
public AccountStatement getStatement() {
for (Component f : list) {
individualStmt = f.getStatement();
compositeStmt.merge(individualStmt);
}
return compositeStmt;
}
}
AccountStatement.java
public class AccountStatement {
public void merge(AccountStatement g) {
//Use this function to merge all account statements
}
}
DepositAccount.java
public class DepositAccount extends Component {
private String accountNo;
private float accountBalance;
private AccountStatement currentStmt;
public DepositAccount(String accountNo, float accountBalance) {
super();
this.accountNo = accountNo;
this.accountBalance = accountBalance;
}
public String getAccountNo() {
return accountNo;
}
public float getBalance() {
return accountBalance;
}
public AccountStatement getStatement() {
return currentStmt;
}
}
SavingsAccount.java
public class SavingsAccount extends Component {
private String accountNo;
private float accountBalance;
private AccountStatement currentStmt;
public SavingsAccount(String accountNo, float accountBalance) {
super();
this.accountNo = accountNo;
this.accountBalance = accountBalance;
}
public String getAccountNo() {
return accountNo;
}
public float getBalance() {
return accountBalance;
}
public AccountStatement getStatement() {
return currentStmt;
}
}
5. Demo
Now, let’s see how the pattern helps in calling the methods transparently without worrying about the object types.
// Creating a component tree
Component component = new CompositeAccount();
// Adding all accounts of a customer to component
component.add(new DepositAccount("DA001", 100));
component.add(new DepositAccount("DA002", 150));
component.add(new SavingsAccount("SA001", 200));
// getting composite balance for the customer
float totalBalance = component.getBalance();
System.out.println("Total Balance : " + totalBalance);
AccountStatement mergedStatement = component.getStatement();
//System.out.println("Merged Statement : " + mergedStatement);
6. Final notes
- The composite pattern defines class hierarchies consisting of individual objects and composite objects.
- Clients treat primitive and composite objects uniformly through a component interface, which makes client code simple.
- Adding new components can be easy, and client code does not need to be changed since the client interacts with the new components through the component interface.
- Composite hierarchy can be traversed with Iterator design pattern.
- Visitor design patterns can be applied to an operation over a composite.
- Flyweight design pattern is often combined with Composite to implement shared leaf nodes.
Happy Learning !!
Comments