I want to explore the difference between recursion approach and composite design pattern. Composite design pattern reminds me of a tree structure. So if I have to write up how it would look in a class diagram, we could have this:

Keeping this class diagram in mind, here is what I have so far in Java; but I don't mind pseudo-code.
Let's create a leaf:
class NumericOperand extends ArithmeticExpression{
public Float add(String:s1,String:s2){
return s1.toFloat() + s2.toFloat()
}
public Float minus(String:s1,String:s2){
return s1.toFloat() - s2.toFloat()
}
public Float multiple(String:s1,String:s2){
return s1.toFloat() * s2.toFloat()
}
public Float divide(String:s1,String:s2){
return s1.toFloat() / s2.toFloat()
}
}
Let's now define composite:
public CompositeOperand extends ArithmeticExpression{
private List<NumericOperand> operandList = new ArrayList<NumericOperand>();
//now what ???
//here im a little lost what i should do ? can you help me ?
}
In the composite what should I be checking exactly? Obviously I need to somehow know if it's an operator or integer here, but I don't know exactly how to put it together.
Here is one example of arithmetic operations implemented using the Composite design pattern. There are any number of ways to implement arithmetic. The class design here is intended simply to highlight the pattern, not necessarily to portray the "best" solution.
The pattern starts with a Component interface, which is shared by Leafs and Composites.
public interface Arithmetic {
double compute();
default void appendChild(Arithmetic arithmetic) {}
default void removeChild(Arithmetic arithmetic) {}
}
Next, we have Leaf nodes, which each represent a singular operation.
public class Addition implements Arithmetic {
private final double x;
private final double y;
public Addition(double x, double y) {
this.x = x;
this.y = y;
}
@Override
public double compute() {
return x + y;
}
}
public class Subtraction implements Arithmetic {
private final double x;
private final double y;
public Subtraction(double x, double y) {
this.x = x;
this.y = y;
}
@Override
public double compute() {
return x - y;
}
}
And finally, a Composite node, which represents multiple operations.
public class CompositeAddition implements Arithmetic {
private final List<Arithmetic> operations = new ArrayList<>();
public CompositeAddition(Arithmetic... arithmetics) {
operations.addAll(Arrays.asList(arithmetics));
}
@Override
public double compute() {
return operations.stream().mapToDouble(Arithmetic::compute).sum();
}
@Override
public void appendChild(Arithmetic arithmetic) {
operations.add(arithmetic);
}
@Override
public void removeChild(Arithmetic arithmetic) {
operations.remove(arithmetic);
}
}
I leave the remaining arithmetic types as an exercise for the reader. These few classes are sufficient for a demonstration.
public class Main {
public static void main(String... args) {
Arithmetic fivePlusTwo = new Addition(5,2);
Arithmetic fiveMinusTwo = new Subtraction(5,2);
Arithmetic sevenPlusThree = new CompositeAddition(fivePlusTwo, fiveMinusTwo);
System.out.println(sevenPlusThree.compute());
}
}
The critical point of the design pattern is that all operations, whether singular or multiple, can be viewed through the same interface. In this way, a client receiving Arithmetic objects is able to compute() them without knowing whether they are leafs or composites.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With