Type Structural
Purpose Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Description

The Composite Pattern is a structural design pattern that allows individual objects and groups of objects to be treated uniformly through a common interface. It is a tree-like organizational structure, where each node in the tree is either an individual object (leaf) or a group of objects (composite).

The beauty of the Composite Pattern is that a composite object can contain any objects that implement the component interface. These could be leaves or other composites. This is what allows the Composite Pattern to easily model hierarchical, tree-like structures.


Overview

Composite
Component The base class that defines the common methods for all primitive and complex objects in the composition.
Leaf A leaf is a basic element of a composite that doesn't have any sub-elements. These are the building blocks of the structure.
Composite This is a class that has the capability to store child components (either other composites or leaves) and implement the operations defined in the base Component class. It delegates most of the work to these child components.

Implementation

public class Employee(string name)
{
    public static readonly Employee Empty = new ("Vacant");
    
    public string Name { get; } = name;
}

// Component

public interface IOrganizationUnit
{
    void Display(int depth);
}

// Leaf

public class Role(string title, Employee? employee = null) : IOrganizationUnit
{
    public string Title { get; } = title;

    public Employee Employee { get; } = employee ?? Employee.Empty;

    public void Display(int depth)
        => Console.WriteLine(new string('-', depth) + Title + ": " + Employee.Name);
}

// Composite

public class Department(string name) : IOrganizationUnit
{
    private readonly List<IOrganizationUnit> _units = [];
    
    public string Name { get; } = name;

    public void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + Name);
        
        foreach (var unit in _units)
        {
            unit.Display(depth + 2);
        }
    }

    public void Add(IOrganizationUnit unit)
        => _units.Add(unit);

    public void Remove(IOrganizationUnit unit)
        => _units.Remove(unit);
}

// Client

public static class CompositeDemo
{
    public static void Execute()
    {
        void Add(Department department, IOrganizationUnit unit)
        {
            department.Add(unit);
        }
        
        // setup departments
        
        var organization = new Department("Code Hermits Inc.");
        var executive = new Department("Executive");
        var sales = new Department("Sales");
        var it = new Department("IT");

        // setup roles
        
        Add(executive, new Role("Chief Executive Officer", new Employee("Mike Smith")));
        Add(sales, new Role("Sales Manager", new Employee("Shirly Chan")));
        Add(it, new Role("IT Manager", new Employee("Rakesh Gupta")));
        Add(it, new Role("Developer", new Employee("Tom Brown")));
        Add(it, new Role("Developer", new Employee("Mary Johnson")));
        Add(it, new Role("DBA"));
        
        // setup department hierarchy
        
        Add(organization, executive);
        Add(executive, sales);
        Add(executive, it);
        
        organization.Display(0);    
    }
}

Summary

For more information, please see here.