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.
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.
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.
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
Prompt: UML diagram of Composite pattern, clear tree structure, minimalist vector style.
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.