Composite Design Pattern
The composite design pattern is a partitioning design pattern. It lets you treat a group of objects the same way you would treat a single object of that kind. In this post, we will try to explore this with an example in Java.
For example, A large arithmetic expression is a composite of smaller expressions. That is, To evaluate a large expression, you would first evaluate its leaf nodes.
As you see here, Operand and Expression both are evaluable. But the important thing to note here is that the expression may contain another expression or an operand. This makes it a composite object. Let’s implement this in java.
Implementing Composite Design Pattern
The composite pattern mainly consists of three parts.
- Component interface
- Leaf Object
- Composite Object
Component interface
The component interface contains the basic operations a leaf or composite would have. In our case, all of our expressions must evaluate
. So We are defining our interface like this.
public interface Evaluable {
public int evaluate();
}
Code language: PHP (php)
Leaf objects
Leaf objects are the individual components of a composite object. For our arithmetic examples, These objects are the operands or literals.
public class Operand implements Evaluable {
private int value;
public Operand(int value) {
this.value = value;
}
@Override
public int evaluate() {
return value;
}
}
Code language: PHP (php)
Composite Pattern
Composite design pattern expects an object to behave as if they were their composition. In our case, the leaves can evaluate to an integer. So the Expression object will also have a evaluate
method.
public class Expression implements Evaluable {
private Evaluable leftOperand;
private Evaluable rightOperand;
private final Operation operation;
public Expression(Evaluable leftOperand, Evaluable rightOperand, Operation operation) {
this.leftOperand = leftOperand;
this.rightOperand = rightOperand;
this.operation = operation;
}
@Override
public int evaluate() {
Integer result = null;
switch (operation) {
case ADD:
result = leftOperand.evaluate() + rightOperand.evaluate();
break;
case SUB:
result = leftOperand.evaluate() - rightOperand.evaluate();
break;
case MUL:
result = leftOperand.evaluate() * rightOperand.evaluate();
break;
case DIV:
result = leftOperand.evaluate() / rightOperand.evaluate();
break;
}
return result;
}
}
Code language: PHP (php)
Here, the Expression
object can take two Evaluable
objects and an operation. Note that evaluables can be an Operand
or another Expression
. This is a good example of a composite pattern. By chaining more and more expressions and numbers, you could create complex results.
A client that creates Composite Objects
With the above setup, you can create composite expressions like this.
Evaluable evaluable = new Operand(5);
System.out.println("Result :" + evaluable.evaluate());
Evaluable expression1 = new Expression(new Operand(3),new Operand(5),Operation.MUL);
System.out.println("Result :" + expression1.evaluate());
Code language: JavaScript (javascript)
We don’t have to stop there. As each expression can take another expression, lets create an expression that represents ( 10 + 2 ) / 6 .
As you see here, The first expression object contains another expression for 10+2 and an operand 6. When we evaluate this, the first expression would result in 12. Which is then evaluated as 12 / 6. Thus the final result is 2.
The important thing to note here is that the operand has evaluate() method. And so is the Expressions. As each expression object directly deals with Evaluable
interface, both of them behave the same from the client’s perspective.
To summarize, you should use the composite pattern whenever the client can use a component or a group of them similarly. You can find examples of composite design pattern in java under our GitHub repository.