The Composite Pattern allows you to treat individual objects and "Groups of Objects" (Composites) identically. This is the standard pattern for building File Systems (Files vs Folders), Organizational Charts (Employee vs Manager), or UI Component Trees.
If you ask for the size of a File, it returns its bytes. If you ask for the size of a Folder, it internally asks all its children for their sizes and sums them up. To the user, they both look like an IFileSystemItem.
public interface IComponent { void Display(); }
public class Leaf : IComponent { ... } // Individual item
public class Composite : IComponent
{
private List<IComponent> _children = new();
public void Display()
{
foreach(var child in _children) child.Display();
}
}
The Composite pattern relies heavily on Recursion. A Composite can contain another Composite, allowing for infinitely deep "Tree" structures.
Q: "Is the Composite pattern a violation of the Interface Segregation Principle (ISP)?"
Architect Answer: "It can be. If you put `Add(child)` and `Remove(child)` methods on the top-level `IComponent` interface, the 'Leaf' node is forced to implement those methods even though it cannot have children. This is a trade-off. You lose **Safety** (because a Leaf might throw an exception if you try to add a child), but you gain **Transparency** (because you can treat every node exactly the same without checking if it is a list or an object). Senior architects usually choose transparency for cleaner client code."