Software

Composite pattern

The pattern achieves 2 goals:

  1. To compose nested structures of objects.
  2. To deal with the classes for these objects uniformly.
Composite Pattern Class Diagram.png
Composite class diagram.

Visualization of the composite:

Composite visualization Diagram.png

The pattern is used to address 2 issues:

  1. 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.
  1. 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:

Composite (Housing) Class Diagram.png
Composite class diagram example.

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

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.