Definition of Composite pattern
In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to “compose” objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
Where to use the Composite pattern?
When we want to implement the same interface on leaves and composites so that they are handled in the same way.
UML example
Implementation of the Composite pattern
First we need to declare the interface that will describe the behavior of our component.
package main.composite; | |
public interface Human { | |
String getName(); | |
String getLastName(); | |
void print(); | |
void addChild(Human child); | |
void addParent(Human parent); | |
} |
Then the implementation will have the same behavior but with some hierarchy between them.
package main.composite; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class GrandParent implements Human{ | |
private String name; | |
private String lastName; | |
@Override | |
public String getName() { | |
return name; | |
} | |
@Override | |
public String getLastName() { | |
return lastName; | |
} | |
public GrandParent(String name, String lastName){ | |
this.name = name; | |
this.lastName = lastName; | |
} | |
@Override | |
public void print() { | |
System.out.println("=============================="); | |
System.out.println("Name : " + getName()); | |
System.out.println("Last name : " + getLastName()); | |
System.out.println("Childs :"); | |
for (Human child: childs) { | |
System.out.println(" - Name : " + child.getName()); | |
} | |
System.out.println("=============================="); | |
} | |
private List<Human> childs = new ArrayList<>(); | |
@Override | |
public void addChild(Human child) { | |
childs.add(child); | |
} | |
@Override | |
public void addParent(Human parent) { | |
} | |
} |
package main.composite; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class Parent implements Human{ | |
private String name; | |
private String lastName; | |
@Override | |
public String getName() { | |
return name; | |
} | |
@Override | |
public String getLastName() { | |
return lastName; | |
} | |
public Parent(String name, String lastName){ | |
this.name = name; | |
this.lastName = lastName; | |
} | |
@Override | |
public void print() { | |
System.out.println("=============================="); | |
System.out.println("Name : " + getName()); | |
System.out.println("Last name : " + getLastName()); | |
System.out.println("Parents :"); | |
for (Human parent: grandParents) { | |
System.out.println(" - Name : " + parent.getName()); | |
} | |
System.out.println("Childs :"); | |
for (Human child: childs) { | |
System.out.println(" - Name : " + child.getName()); | |
} | |
System.out.println("=============================="); | |
} | |
private List<Human> childs = new ArrayList<>(); | |
@Override | |
public void addChild(Human child) { | |
childs.add(child); | |
} | |
private List<Human> grandParents = new ArrayList<>(); | |
@Override | |
public void addParent(Human parent) { | |
grandParents.add(parent); | |
} | |
} |
package main.composite; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class Child implements Human{ | |
private String name; | |
private String lastName; | |
@Override | |
public String getName() { | |
return name; | |
} | |
@Override | |
public String getLastName() { | |
return lastName; | |
} | |
public Child(String name, String lastName){ | |
this.name = name; | |
this.lastName = lastName; | |
} | |
@Override | |
public void print() { | |
System.out.println("=============================="); | |
System.out.println("Name : " + getName()); | |
System.out.println("Last name : " + getLastName()); | |
System.out.println("Parents :"); | |
for (Human parent: parents) { | |
System.out.println(" - Name : " + parent.getName()); | |
} | |
System.out.println("=============================="); | |
} | |
@Override | |
public void addChild(Human child) { | |
} | |
private List<Human> parents = new ArrayList<>(); | |
@Override | |
public void addParent(Human parent) { | |
parents.add(parent); | |
} | |
} |
The only difference in these implementations are the use of the addParent() and addChild() to create the hierarchy like we can see the following example and the output it will produce.
package main.composite; | |
public class CompositeMain { | |
public static void main(String[] args) { | |
Child mathys = new Child("Mathys", "Le Tutour"); | |
Parent erwan = new Parent("Erwan", "Le Tutour"); | |
Parent amelie = new Parent("Amelie", "Le Tutour"); | |
mathys.addParent(erwan); | |
mathys.addParent(amelie); | |
erwan.addChild(mathys); | |
amelie.addChild(mathys); | |
GrandParent philippe = new GrandParent("Philippe", "Le Tutour"); | |
philippe.addChild(erwan); | |
erwan.addParent(philippe); | |
philippe.print(); | |
erwan.print(); | |
mathys.print(); | |
} | |
} |
==============================
Name : Philippe
Last name : Le Tutour
Childs :
- Name : Erwan
==============================
==============================
Name : Erwan
Last name : Le Tutour
Parents :
- Name : Philippe
Childs :
- Name : Mathys
==============================
==============================
Name : Mathys
Last name : Le Tutour
Parents :
- Name : Erwan
- Name : Amelie
==============================
Top comments (2)
Thanks. straightforward.
thank you for your reading time, happy that this tutorial was able to help.