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