Composite Design Pattern: Comprehensive Explanation

The Composite pattern is a structural design pattern that composes objects into tree structures to represent part-whole hierarchies. It allows clients to treat individual objects and compositions uniformly, simplifying interactions with complex, nested structures.


Core Intent

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

This pattern enables transparent recursion over hierarchical data, where leaves and composites are interchangeable.


When to Use Composite

ScenarioUse Case
Hierarchical data structures existe.g., File systems, UI menus, product catalogs
Need to treat leaves and composites alikeUniform operations (e.g., “render all”, “calculate total”)
Dynamic composition at runtimeAdd/remove children without changing client code
Recursive operations on treesTraverse and process nested elements
GUI components with nestingPanels containing buttons, which contain icons

Avoid when:

  • Hierarchy is flat/simple → Overkill
  • Operations differ significantly between leaves/composites → Use Visitor

Where It Is Used in Real Systems

DomainExample
File SystemsDirectories (composite) containing files (leaf)
UI FrameworksPanels (composite) with buttons/labels (leaf)
XML/HTML DOMElements (composite) with text nodes (leaf)
E-CommerceCategories (composite) with products/subcategories (leaf)
GraphicsGroups (composite) of shapes (leaf)

Key Benefits

  • Uniformity: Single interface for leaves and composites
  • Encapsulation: Hierarchy details hidden from clients
  • Extensibility: Add new component types easily
  • Simplified traversal: Recursive operations on trees
  • Single Responsibility: Components manage own children

Real-World Example: E-Commerce Product Catalog Hierarchy

An e-commerce platform models a product catalog as a tree:

  • Categories (e.g., “Electronics”) contain subcategories (e.g., “Laptops”) and products (e.g., “Dell XPS”).
  • Operations like display catalog, calculate total inventory value, or search treat categories and products uniformly.

This allows dynamic nesting (add/remove products/categories) and recursive processing (e.g., total price across all subtrees).


C# Implementation

using System;
using System.Collections.Generic;
using System.Linq;

// ==================== COMPONENT ====================

public interface IProductComponent
{
    string Name { get; }
    decimal GetPrice();
    void Display(int indent = 0);
    void Add(IProductComponent component);
    void Remove(IProductComponent component);
    IEnumerable<IProductComponent> GetChildren();
}

// ==================== LEAF ====================

public class ProductItem : IProductComponent
{
    public string Name { get; }
    private readonly decimal _price;

    public ProductItem(string name, decimal price)
    {
        Name = name;
        _price = price;
    }

    public decimal GetPrice() => _price;

    public void Display(int indent = 0)
    {
        Console.WriteLine(new string(' ', indent * 2) + $"└── Product: {Name} - ₹{_price:F2}");
    }

    public void Add(IProductComponent component)
        => throw new InvalidOperationException("Products cannot have children.");

    public void Remove(IProductComponent component)
        => throw new InvalidOperationException("Products cannot have children.");

    public IEnumerable<IProductComponent> GetChildren() => Enumerable.Empty<IProductComponent>();
}

// ==================== COMPOSITE ====================

public class ProductCategory : IProductComponent
{
    public string Name { get; }
    private readonly List<IProductComponent> _children = new();

    public ProductCategory(string name)
    {
        Name = name;
    }

    public decimal GetPrice()
    {
        return _children.Sum(child => child.GetPrice());
    }

    public void Display(int indent = 0)
    {
        Console.WriteLine(new string(' ', indent * 2) + $"┌── Category: {Name} (Total: ₹{GetPrice():F2})");
        foreach (var child in _children)
        {
            child.Display(indent + 1);
        }
    }

    public void Add(IProductComponent component)
    {
        _children.Add(component);
    }

    public void Remove(IProductComponent component)
    {
        _children.Remove(component);
    }

    public IEnumerable<IProductComponent> GetChildren() => _children;
}

// ==================== CLIENT ====================

public class CatalogManager
{
    private readonly IProductComponent _root;

    public CatalogManager(IProductComponent root)
    {
        _root = root;
    }

    public void DisplayCatalog()
    {
        _root.Display();
    }

    public decimal GetTotalCatalogValue()
    {
        return _root.GetPrice();
    }

    public void AddToCatalog(IProductComponent component)
    {
        if (_root is ProductCategory category)
            category.Add(component);
    }
}

// ==================== DEMO ====================

class Program
{
    static void Main()
    {
        // Build hierarchy
        var electronics = new ProductCategory("Electronics");
        var laptops = new ProductCategory("Laptops");
        laptops.Add(new ProductItem("Dell XPS", 120000m));
        laptops.Add(new ProductItem("MacBook Pro", 150000m));

        var phones = new ProductCategory("Phones");
        phones.Add(new ProductItem("iPhone 15", 80000m));
        phones.Add(new ProductItem("Samsung S24", 70000m));

        electronics.Add(laptops);
        electronics.Add(phones);

        var manager = new CatalogManager(electronics);

        Console.WriteLine("=== COMPOSITE PATTERN IN E-COMMERCE ===\n");
        manager.DisplayCatalog();
        Console.WriteLine($"\nTotal Catalog Value: ₹{manager.GetTotalCatalogValue():F2}");
    }
}

Sample Output

=== COMPOSITE PATTERN IN E-COMMERCE ===

┌── Category: Electronics (Total: ₹470000.00)
  ├── Category: Laptops (Total: ₹270000.00)
  │   └── Product: Dell XPS - ₹120000.00
  │   └── Product: MacBook Pro - ₹150000.00
  ├── Category: Phones (Total: ₹150000.00)
      └── Product: iPhone 15 - ₹80000.00
      └── Product: Samsung S24 - ₹70000.00

Total Catalog Value: ₹470000.00

UML Class Diagram

Participants in the Composite Pattern

The classes and objects participating in this pattern include:

  • Component (IProductComponent)
    • Declares the common interface for both leaf and composite objects.
    • Defines operations like Display(), GetPrice().
  • Leaf (ProductItem)
    • Represents primitive elements with no children.
    • Implements component operations directly.
  • Composite (ProductCategory)
    • Defines behavior for components with children.
    • Stores child components and delegates operations (e.g., sum prices recursively).
  • Client
    • Works with Component references, unaware of leaf vs. composite.

Summary Table

ParticipantRole in E-Commerce Example
ComponentIProductComponent – common interface for products/categories
LeafProductItem – atomic product with price
CompositeProductCategory – container for sub-items
ClientCatalogManager – operates on hierarchy uniformly

Advantages in E-Commerce

BenefitImpact
Scalable catalogsNest categories dynamically
Uniform operationsSearch/display across entire tree
Recursive queriesTotal value, inventory count
ExtensibleAdd new component types (e.g., bundles)

Composite vs Decorator

AspectCompositeDecorator
StructureTree hierarchy (part-whole)Wrapper chain (add behavior)
PurposeGroup objectsEnhance single object
ExampleCatalog treeProduct with wrapper (e.g., discount)
ChildrenMany (recursive)Single (linear)

Conclusion

The Composite pattern is ideal for e-commerce catalogs, where nested categories and products form a tree. It provides transparent handling of hierarchies, enabling efficient traversal and operations while maintaining flexibility for dynamic content management.

Employed in ASP.NET Core (view components), XML parsers, and e-commerce platforms like Shopify for menu/product trees.

Uma Mahesh
Uma Mahesh

Author is working as an Architect in a reputed software company. He is having nearly 21+ Years of experience in web development using Microsoft Technologies.

Articles: 283