Composite

The composite pattern

The composite pattern is a structural pattern and is a way of creating similar objects that form a tree like structure.
It's difficult to find a reason for this pattern but imagine a simplified construction of the graphics on this page.
We have pictures, text, lines, rectangles etc, well the pictures could contain text, lines and rectangles, also, the pictures could contain pictures and the rectangles would almost definitely contain lines.
The object structure would be similar to:
Tree image

It's clear that we need some sort of tree structure, this leads to the inheritance graph below.
Structure image

Now, the structure I've created is a little different to the one in Design Patterns [GOF] and the reason is to prevent stamp coupling.
The GOF design has the abstract class Component with the methods:
  • Operation()
  • Add(Component)
  • Remove(Component)
  • GetChild(int) (?)
Unfortunately, this causes stamp coupling as all inherited classes would have to implement each method but for a Leaf this is unnecessary.


So after some fancy pictures, we go into an example, with the creation of the Component abstraction:
abstract class Component {
    private string name;
    private int layer;

    public Component(string name) {
        this.name = name;
    }
    public virtual void Operation(int layer) {
        this.layer = layer;
        OperationCommonCodeTemplate();
    }
    protected virtual void OperationCommonCodeTemplate() {
        Console.WriteLine(new String('-', layer) + name);
    }
}
Things to notice with the code are the int layer member variable which just adds a little flair as it adds 'dashes' recursively before showing the name of the Component and the OperationCommonCodeTemplate method this is part of the Template Method Pattern and I'm using it to shore-up some common code that can be overridden.

The implementation of a leaf of the tree is very simple in my example and is:
class Leaf : Component {
    public Leaf(string name) : base(name) { }
}

The implementation of the composite part, which is a little more interesting, is:
class Composite : Component {
    private List components = new List();
    public Composite(string name) : base(name) { }

    public override void Operation(int layer) {
        base.Operation(layer);
        foreach (Component component in components) {
            component.Operation(layer + 1);
        }
    }
    public void Add(Component component) {
        components.Add(component);
    }
    public void Remove(Component component) {
        components.Remove(component);
    }
}

Here's some test code to test the implementation:
static void Main(string[] args) {
    Component leafA = new Leaf("LeafA");
    Component leafB = new Leaf("leafB");
    Component leafC = new Leaf("leafC");

    Composite compositeA = new Composite("compositeA");
    Component leafD = new Leaf("leafD");
    Component leafE = new Leaf("leafE");

    compositeA.Add(leafA);
    compositeA.Add(leafB);
    compositeA.Add(leafC);

    Composite root = new Composite("root");

    root.Add(compositeA);
    root.Add(leafD);
    root.Add(leafE);

    root.Operation(0);

    Console.ReadKey();
}
And the output:
root
-compositeA
--LeafA
--leafB
--leafC
-leafD
-leafE

Summary

That's the composite pattern. I've changed the implementation compared to the GOF book, but the late John Vlissades in his excellent follow up book, Pattern Hatching, makes a valid argument that you don't know if the leaf in the future will need the same functionality as the composite so there's always a trade off, and the developer needs to understand the problem to be solved and use his/her strategic judgement.

References

wiki
Design Patterns [GOF]
Pattern Hatching Vlissides
dofactory composite pattern
tutorialspoint composite pattern