The pattern achieves 2 goals:
- To compose nested structures of objects.
- To deal with the classes for these objects uniformly.

Visualization of the composite:

The pattern is used to address 2 issues:
- How do we use individual types of objects to build a tree-like structure? – The composite class is capable of aggregating component classes, which will create a tree-like structure.
- How can we treat the individual types of objects uniformly without checking their types? – Each individual class is a subtype of an interface or superclass, and will be able to conform to a set of shared behaviors.
Example:
%20Class%20Diagram.png?raw=true)
Step1: Design the interface that defines the overall type
public interface IStructure {
public void Enter();
public void Exit();
public void Location();
public string GetName();
}
Step 2: Implement the composite class
public class Housing: IStructure {
private ArrayList<IStructure> structures;
private string address;
public Housing(string address){
this.structures = new ArrayList<IStructure>();
this.address = address;
}
public int AddStructure(IStructure component) {
this.structures.add(component);
return this.structure.Length;
}
public IStructure GetStructure(int componentNumber) {
return this.structures.get(componentNumber);
}
public void Location() {
System.WriteLine("You are currently in " + this.getName() + ". It has: ");.
foreach(IStructure struct in this.structures) {
System.WriteLine(struct.getName());
}
}
public void Enter() {...}
public void Exit() {...}
}
Step 3: Implement the leaf class
public abstract class Room: IStructure {
public string Name;
public void Enter(){
//...
}
public void Exit(){
//...
}
public void Location(){
System.WriteLine("You are currently in the " + this.Name);
}
public string GetName(){
return this.Name;
}
}
Client usage:
public class Program {
public static void Main(String[] args) {
Housing building = new Housing("100 Street");
Housing floor1 = new Housing("100 Street - First floor");
int firstFloor = building.addStructure(floor1);
Room washroom1m = new Room("1F Men's Washroom");
Room washroom1f = new Room("1F Women's Washroom");
Room common = new Room("1F Common Area");
int firstMens = floor1.AddStructure(washroom1m);
int firstWomens = floor1.AddStructure(washroom1f);
int firstCommon = floor1.AddStructure(common);
building.enter();
Housing currentFloor = building.GetStructure(firstFloor);
currentFloor.enter();
Room currentRoom = currentFloor.GetStructure(firstMens);
currentRoom.enter();
currentRoom = currentFloor.GetStructure(firstCommon);
currentRoom.enter(); //walk into the common area
}
}
To summarize the composite design pattern is used to solve the issues of how to build a tree-like structure of objects, and how to treat the individual types of those objects uniformly. This is achieved by enforcing polymorphism across each class through implementing an interface or inheriting from a base class and using a technique called recursive composition which allows objects to be composed of other objects that are of a common type.
(Decomposition and generalization design principles together)
One thought on “Composite pattern”