In many .NET applications, there is a need to work with hierarchical structures: menus, directories and files, UI components, nodes in a tree, product categories, etc.
The problem? Sometimes you need to treat individual objects and groups of objects in the same way.
This is where the Composite Pattern comes in, a structural pattern that allows uniform treatment of simple and composite objects. It models "tree" structures so that clients are not forced to know whether they are working with a leaf or a composite node.
🎯 Why Composite Pattern is Useful
Composite is ideal when we have:
-
tree structures (menus, file systems, categories)
-
objects that can contain other objects
-
need for uniform operations for simple and composite elements
-
recursion scenarios
Goal: uniformity + simplicity.
The client calls the same methods, regardless of the node type.
🧱 Composite Pattern Structure
-
Component — the common interface for all objects in the tree
-
Leaf — individual object (e.g., file, menu item)
-
Composite — contains other components (e.g., directory, main menu)
🧩 Simple Example in C#
Let's model a menu system:
🟦 Component – common interface
public interface IMenuComponent
{
string Name { get; }
void Display(int depth = 0);
}
🟩 Leaf – simple menu element
public class MenuItem : IMenuComponent
{
public string Name { get; }
public MenuItem(string name)
{
Name = name;
}
public void Display(int depth = 0)
{
Console.WriteLine(new string('-', depth) + Name);
}
}
🟧 Composite – group of elements
public class MenuGroup : IMenuComponent
{
public string Name { get; }
private readonly List<IMenuComponent> _children = new();
public MenuGroup(string name)
{
Name = name;
}
public void Add(IMenuComponent component) => _children.Add(component);
public void Remove(IMenuComponent component) => _children.Remove(component);
public void Display(int depth = 0)
{
Console.WriteLine(new string('-', depth) + Name);
foreach (var child in _children)
child.Display(depth + 2);
}
}
▶️ Usage
var mainMenu = new MenuGroup("Main Menu");
var fileMenu = new MenuGroup("File");
var editMenu = new MenuGroup("Edit");
fileMenu.Add(new MenuItem("New"));
fileMenu.Add(new MenuItem("Open"));
fileMenu.Add(new MenuItem("Save"));
editMenu.Add(new MenuItem("Copy"));
editMenu.Add(new MenuItem("Paste"));
mainMenu.Add(fileMenu);
mainMenu.Add(editMenu);
mainMenu.Display();
📌 Output:
Main Menu
--File
----New
----Open
----Save
--Edit
----Copy
----Paste
The structure can be extended recursively, without changes in the client code.
✔️ Benefits
-
uniform treatment for simple and composite objects
-
easy extension (add new nodes without changing existing code)
-
elegantly models tree structures
-
reduces duplicate code
❗ Disadvantages
-
may hide differences between nodes (if some should not have children)
-
increases the number of classes
-
some operations may be inappropriate for "leaf" nodes
🔚 Conclusion
The Composite Pattern is excellent for applications that manage complex hierarchical structures and allows their manipulation in an elegant, uniform, and scalable way. It is often used in UI frameworks, menu systems, graphic editors, file systems, product catalogs, etc.