Design Pattern / Structural

[Design Pattern] Composite Pattern

A tree-structure pattern that treats individual objects and composed objects through the same interface.

  • Design Pattern
  • Structural
Contents

One-line pattern summary

A tree-structure pattern that treats individual objects and composed objects through the same interface.

Typical Unity use cases

  • When building quest objectives as a tree.
  • When handling node and group node objects in the same way.

Parts (roles)

  • Component
  • Leaf
  • Composite

Unity example (C#)

The code below is a simplified Unity example based on the scenario described above.

using System.Collections.Generic;

public interface IQuestCondition
{
    bool IsCompleted();
}

public sealed class KillMonsterCondition : IQuestCondition
{
    public bool IsCompleted() => false;
}

public sealed class AllConditionsGroup : IQuestCondition
{
    private readonly List<IQuestCondition> childConditions = new();

    public void Add(IQuestCondition childCondition)
    {
        childConditions.Add(childCondition);
    }

    public bool IsCompleted()
    {
        foreach (IQuestCondition childCondition in childConditions)
        {
            if (!childCondition.IsCompleted())
            {
                return false;
            }
        }
        return true;
    }
}

Advantages

  • It clarifies module boundaries and reduces coupling.
  • Features can be extended or integrated without modifying existing code.

Things to watch out for

  • If wrapper layers become too deep, debugging gets harder.
  • Interfaces should stay small so responsibility boundaries do not blur.

Interaction diagram

This shows the recursive flow where both single objects and composites are handled through the same interface.

flowchart TD

  client["Client"]
  root["UIRoot (Composite)"]
  panel["Panel (Composite)"]
  button["Button (Leaf)"]
  text_label["Label (Leaf)"]
  render["Render()"]

  client -- "render()" --> root
  root -->|render child| panel
  panel -->|render child| button
  panel -->|render child| text_label
  button --> render
  text_label --> render

Comments