Composite Design Pattern in C# with Example

1. Definition

The Composite Pattern is a structural design pattern that allows you to compose objects into tree structures to represent whole-part hierarchies. This pattern treats both individual objects and composites (groups of objects) uniformly, enabling you to use recursive methods to manage the hierarchy.

2. Problem Statement

Imagine you have a system that deals with graphical elements. Some of these elements might be simple shapes like circles or rectangles, while others can be complex structures composed of several shapes. If we treat simple shapes and their compositions differently, the client code gets complex when trying to process graphical elements.

3. Solution

The solution is to define an abstract base class or interface (Component) which declares the behavior of the component in a composition. Both the primitive objects (Leaf) and the composite objects (Composite) inherit from this base class or implement the interface.

4. Real-World Use Cases

1. Graphics systems where shapes can be composed of other shapes.

2. File and folder systems.

3. Organization structures, where an employee can be an individual or a manager of a team.

5. Implementation Steps

1. Define a component interface to ensure that concrete components have a common set of methods.

2. Create leaf classes that implement the component interface.

3. Create a composite class that, besides implementing the component interface, holds a collection of children components.

6. Implementation in C#

// Step 1: Component Interface
public interface IGraphic
{
    void Draw();
}

// Step 2: Leaf Classes
public class Circle : IGraphic
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle.");
    }
}

public class Rectangle : IGraphic
{
    public void Draw()
    {
        Console.WriteLine("Drawing a rectangle.");
    }
}

// Step 3: Composite Class
public class CompoundGraphic : IGraphic
{
    private List<IGraphic> _children = new List<IGraphic>();

    public void Add(IGraphic child)
    {
        _children.Add(child);
    }

    public void Remove(IGraphic child)
    {
        _children.Remove(child);
    }

    public void Draw()
    {
        foreach (var child in _children)
        {
            child.Draw();
        }
    }
}

public class Program
{
    public static void Main()
    {
        // Creating individual leaf objects
        var circle = new Circle();
        var rectangle = new Rectangle();

        // Creating a composite
        var compoundGraphic = new CompoundGraphic();
        compoundGraphic.Add(circle);
        compoundGraphic.Add(rectangle);

        // Drawing all components
        compoundGraphic.Draw();
    }
}

Output:

Drawing a circle.
Drawing a rectangle.

Explanation:

The Composite Pattern enables you to work with complex tree structures more easily. In this example, Circle and Rectangle are the leaf nodes, while CompoundGraphic acts as the composite that can group multiple graphics. By treating both individual shapes and their compositions uniformly, the client code can invoke the Draw method transparently, regardless of whether it's a single shape or a composite.

7. When to use?

1. Use the Composite Pattern when you need to represent part-whole hierarchies of objects.

2. When you want the client code to treat individual objects and composites uniformly.

3. When the structure can have any level of nesting.


Comments