Patrón Composite en C#: Guía Completa con Ejemplos

Introducción: Un árbol, una sola vista

Composite permite tratar objetos individuales y grupos de objetos de la misma forma. Es ideal cuando tienes estructuras jerárquicas como árboles, menús, carpetas o componentes UI.

Si un archivo y una carpeta se pueden "mostrar" con el mismo método, el cliente no necesita saber si trata con un elemento simple o compuesto.

Árbol con ramas, símbolo del Composite
Prompt: Majestic tree with clear branching structure, aerial view, natural symmetry, high detail.

1. La Naturaleza: Árboles y Ramas

Un árbol está compuesto por ramas, y cada rama puede contener más ramas. Para la naturaleza, todas son ramas, aunque estén en distintos niveles.

Composite hace lo mismo: un nodo hoja y un nodo compuesto comparten la misma interfaz.

Ramas en niveles jerárquicos
Prompt: Close-up of tree branches forming hierarchical layers, soft sunlight, botanical style.

2. Mundo Real: Carpetas y Archivos

En un sistema operativo, una carpeta puede contener archivos y otras carpetas. Si pides "tamaño" a un archivo o a una carpeta, ambos responden con el mismo método, pero la carpeta calcula el total de sus hijos.

Estructura de carpetas y archivos
Prompt: Clean folder tree UI, minimalist file explorer, blue accent, high resolution.

3. Implementación en C#: Código Paso a Paso

3.1 La interfaz común

public interface IElementoArchivo
{
    string Nombre { get; }
    long ObtenerTamano();
    void Mostrar(int nivel = 0);
}

3.2 Hoja: Archivo

public class Archivo : IElementoArchivo
{
    public string Nombre { get; }
    private long _tamano;

    public Archivo(string nombre, long tamano)
    {
        Nombre = nombre;
        _tamano = tamano;
    }

    public long ObtenerTamano() => _tamano;

    public void Mostrar(int nivel = 0)
    {
        Console.WriteLine(new string(' ', nivel * 2) + $"📄 {Nombre} ({_tamano} KB)");
    }
}

3.3 Compuesto: Carpeta

public class Carpeta : IElementoArchivo
{
    public string Nombre { get; }
    private List _hijos = new List();

    public Carpeta(string nombre)
    {
        Nombre = nombre;
    }

    public void Agregar(IElementoArchivo elemento) => _hijos.Add(elemento);
    public void Quitar(IElementoArchivo elemento) => _hijos.Remove(elemento);

    public long ObtenerTamano()
    {
        return _hijos.Sum(h => h.ObtenerTamano());
    }

    public void Mostrar(int nivel = 0)
    {
        Console.WriteLine(new string(' ', nivel * 2) + $"📁 {Nombre}");
        foreach (var hijo in _hijos)
        {
            hijo.Mostrar(nivel + 1);
        }
    }
}

3.4 Uso

var raiz = new Carpeta("/proyecto");
raiz.Agregar(new Archivo("README.md", 12));

var src = new Carpeta("src");
src.Agregar(new Archivo("main.cs", 50));
src.Agregar(new Archivo("utils.cs", 20));

raiz.Agregar(src);

raiz.Mostrar();
Console.WriteLine($"Tamaño total: {raiz.ObtenerTamano()} KB");

4. Composite vs Decorator

Composite agrupa objetos en jerarquía. Decorator añade responsabilidades dinámicas a un objeto. Si quieres tratar un grupo como un objeto, usa Composite. Si quieres añadir comportamiento a un objeto sin crear subclases, usa Decorator.

5. Diagrama UML y Definición Formal

UML Composite
Prompt: UML diagram of Composite pattern, clear tree structure, minimalist vector style.
Composite en estructura jerárquica
Prompt: Abstract hierarchy diagram with nodes and leaves, modern infographic style.
Composite es un patrón estructural que compone objetos en estructuras de árbol para representar jerarquías parte-todo, permitiendo que el cliente trate objetos individuales y compuestos de forma uniforme.

⚠️ Cuándo NO Usar Composite

  • Si no hay jerarquía real, introduces complejidad innecesaria.
  • Si los nodos hoja y compuestos tienen operaciones muy distintas.

💪 Ejercicio para Practicar

Crea un menú de restaurante con categorías (compuestos) y platos (hojas). Implementa Mostrar() para imprimir la carta completa.

Conclusión

Composite te permite pensar en términos de árboles sin complicar al cliente. Una sola interfaz para hojas y compuestos es la clave de su poder.