# El patrón Composite: ejemplos de soluciones para jerarquías parte-todo

Las estructuras de datos dinámicas requieren una escructura **jerárquica clara y concisa**. A menudo, llevar tales estructuras a la práctica no resulta nada fácil. No es nada eficiente, por ejemplo, consultar cada vez el tipo de un objeto antes de que los datos se hayan procesado. En particular, cuando muchos objetos simples se encuentran con objetos compuestos, se recomienda usar el patrón de diseño Composite. Al ocultarles sus diferencias, este paradigma de desarrollo de software facilita a los clientes actuar del mismo modo ante los objetos simples y compuestos.

## ¿Qué es el patrón Composite?

El patrón de diseño Composite (Composite Pattern) es uno de los 23 [patrones de diseño](https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/que-son-los-design-patterns/ "¿Qué son los design patterns?") “GoF” para el desarrollo de *software* que fueron publicados en 1994 por Erich Gamma, Richard Helm, Ralph Johnson, y John Vlissides, los llamados “Gang of Four” o la banda de los cuatro. Así como el [patrón Facade](https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/facade-pattern/ "Facade pattern") y el [patrón Decorator](https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/que-es-el-patron-de-diseno-decorator/ "¿Qué es el patrón de diseño Decorator?"), se trata de un patrón de diseño que **agrupa objetos complejos y clases en estructuras mayores.**

El concepto básico del patrón Composite consiste en representar **objetos simples** y sus ***containers*** (o contenedores, también llamados colecciones en algunos lenguajes, o sea: grupos de objetos) en una clase abstracta de manera que puedan ser tratados uniformemente. Este tipo de estructura se conoce como **jerarquía parte-todo** (en inglés: *part-whole hierarchy*), en la que un objeto es siempre, o una **parte de un todo**, o **un todo compuesto por varias partes**.

## ¿Qué problemas resuelve un diagrama UML de patrón Composite?

La finalidad del patrón Composite es, como en todos los patrones “GoF”, **mejorar la gestión de problemas de diseño recurrentes en la programación orientada a objetos**. El resultado deseado es un *software* flexible, caracterizado por objetos fácilmente implementables, intercambiables, reutilizables y testeables. A tal efecto, el patrón de diseño Composite describe un método según el cual los objetos simples y complejos pueden ser tratados de la misma manera. De este modo, se puede crear una estructura de objetos **fácilmente inteligible** que **permite al cliente un acceso altamente eficiente**. Además, también se minimiza la probabilidad de error en el código.

## Patrón de diseño Composite: representación gráfica (UML)

Para implementar jerarquías parte-todo, el patrón Composite proporciona una interfaz de componentes unificada para los objetos simples, también llamados **objetos *leaf*** (hoja, en inglés), y los objetos complejos. Los objetos *leaf* simples integran esta interfaz directamente, mientras que los objetos complejos envían **peticiones específicas del cliente automáticamente a la interfaz** y a sus componentes subordinados. Para el cliente, resulta totalmente indiferente de qué tipo de objeto se trate (parte o todo) ya que solo se comunica con la interfaz.

El siguiente diagrama de clases en formato [UML](https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/uml-lenguaje-unificado-de-modelado-orientado-a-objetos/ "UML: lenguaje unificado de modelado orientado a objetos") muestra más claramente las **conexiones y jerarquías** de un software basado en patrón Composite.

[![Imagen: Diagrama UML de patrón Composite](https://www.ionos.mx/digitalguide/fileadmin/_processed_/a/c/csm_diagrama-uml-de-patron-composite_539ed6d1d2.webp "Diagrama UML de patrón Composite")](https://www.ionos.mx/digitalguide/fileadmin/DigitalGuide/Schaubilder/diagrama-uml-de-patron-composite.png) Los objetos leaf y los objetos complejos son consultados uniformemente por el cliente en jerarquías parte-todo, de acuerdo con el patrón Composite (a través de una interfaz unificada). Los objetos complejos derivan las consultas a sus elementos child.       ##  Pros y contras del patrón de diseño Composite

El patrón Composite es una constante en el desarrollo de *software*. Los proyectos con **estructuras altamente anidadas** tienden a beneficiarse de la práctica metodología de los objetos: ya sean objetos simples o complejos, con dependencias simples o complejas. El alcance del anidamiento es irrelevante en el patrón Composite. Las diferencias entre los tipos de objetos pueden ser ignoradas por el cliente de manera que las consultas no requieren funciones especiales, lo que conlleva la ventaja de que el código del cliente resulta simple y conciso.

Otra ventaja del patrón Composite es la **flexibilidad** y sencilla **escalabilidad** que el patrón otorga al *software*. La interfaz con componentes universales permite la integración de objetos simples y complejos sin modificaciones en el código –ya sea en el cliente o en estructuras de objetos ya existentes.

Pero, a pesar de todas la ventajas, el patrón Composite y su interfaz unificada tienen algunos inconvenientes. La **interfaz** puede convertirse en un dolor de cabeza para los desarrolladores, ya que la **implementación** requiere algunas consideraciones nada desdeñables. Por ejemplo, se debe decidir de antemano qué operaciones van a ser definidas en la interfaz y cuáles en las clases Composite. **Ajustes posteriores de las propiedades Composite** (por ejemplo, restringir qué tipo de elementos *child* se permiten) resultan generalmente **complicados** y difíciles de implementar.

<table>
  <thead>
    <tr>
      <th>Ventajas</th>
      <th>Desventajas</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Facilita la representación de estructuras altamente anidadas</td>
      <td>Implementación de interfaz de componentes complicada</td>
    </tr>
    <tr>
      <td>Código simple y conciso</td>
      <td>Ajustes posteriores de las propiedades Composite complicados</td>
    </tr>
    <tr>
      <td>Gran escalabilidad</td>
      <td></td>
    </tr>
  </tbody>
</table>

## Campos de aplicación del patrón Composite

Utilizar el patrón Composite compensa cuando existe la necesidad de realizar operaciones en estructuras de datos dinámicas con **jerarquías complejas** (en términos de profundidad y anchura). Esto también se conoce como **escructura de árbol binaria**, que resulta especialmente interesante para una amplia variedad de programas. Algunos ejemplos típicos:

**Sistemas de datos**: los [sistemas de datos](https://www.ionos.mx/digitalguide/servidores/know-how/sistemas-de-archivos/ "Sistemas de archivos") figuran entre los componentes más importantes de un *software* de dispositivo. Estos se pueden representar perfectamente usando el patrón Composite: los **ficheros** simples se representan como objetos *leaf* y las **carpetas** (que pueden contener asimismo ficheros u otras carpetas) como objetos complejos.

**Menús de *software***: los menús de programa representan una aplicación típica de una estructura de árbol binaria de acuerdo al patrón de diseño Composite. La **barra de menú** contiene una o más entradas principales (objetos complejos) como, por ejemplo, “Archivo”. Estas entradas principales proporcionan acceso a varios objetos del menú que pueden seleccionarse directamente (objetos *leaf*) o que contienen otros submenús (objetos complejos).

**Interfaces gráficas de usuario (GUI)**: las estructuras de árbol y el patrón Composite también juegan un papel importante en el diseño de [interfaces gráficas de usuario](https://www.ionos.mx/digitalguide/paginas-web/diseno-web/ui-que-es-una-interfaz-de-usuario/ "UI: ¿qué es una interfaz de usuario?"). Aparte de simples objetos *leaf* como botones, campos de texto o casillas de selección, los *containers*, como paneles o marcos, permiten una estructura limpia y una mayor claridad.

## Ejemplo de código: patrón Composite

El patrón Composite está más ampliamente afianzado en el lenguaje de programación Java. El patrón, entre otras cosas, es la base del **AWT (Abstract Window Toolkit)**. El AWT es una práctica y extendida API con unas 50 clases de Java listas para utilizar para el desarrollo de interfaces Java multiplataforma. En el siguiente código de ejemplo, extraído del artículo [*Patrón de diseño Composite en Java* en baeldung.com](https://www.baeldung.com/java-composite-pattern "baeldung.com: Composite Design Pattern in Java"), nos centramos en este popular lenguaje de programación.

En nuestro ejemplo, se muestra una **estructura jerárquica de departamentos en una empresa**. Como primer paso, se define la **interfaz del objeto** *Department*:

```none
public interface Department {
	void printDepartmentName();
}
```

A continuación, se definen **dos simples clases *leaf*:** *FinancialDepartment* (para el departamento fiscal) y *SalesDepartment* (para el departamento de ventas). Ambas **implementan** el método printDepartmentName() de la **interfaz del objeto**, pero no contienen otros objetos *Department*.

```none
public class FinancialDepartment implements Department {
	private Integer id;
	private String name;
	public void printDepartmentName() {
		System.out.println(getClass().getSimpleName());
	}
	// standard constructor, getters, setters
}
```

```none
public class SalesDepartment implements Department {
	private Integer id;
	private String name;
	public void printDepartmentName() {
		System.out.println(getClass().getSimpleName());
	}
	// standard constructor, getters, setters
}
```

Una clase ***composite*** que encaja con la jerarquía se define como “*HeadDepartment*”. Esta consiste en varios objetos *Department* y, además del método *printDepartmentName()*, contiene también otros métodos adicionales para añadir objetos (*addDepartment*) o eliminar objetos ya existentes (r*emoveDepartment*):

```none
public class HeadDepartment implements Department {
	private Integer id;
	private String name;
	private List<department> childDepartments;</department>
	public HeadDepartment(Integer id, String name) {
		this.id = id;
		this.name = name;
		this.childDepartments = new ArrayList<>();
	}
	public void printDepartmentName() {
		childDepartments.forEach(Department::printDepartmentName);
	}
	public void addDepartment(Department department) {
		childDepartments.add(department);
	}
	public void removeDepartment(Department department) {
		childDepartments.remove(department);
	}
}
```


This is a markdown version of: [https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/patron-composite/](https://www.ionos.mx/digitalguide/paginas-web/desarrollo-web/patron-composite/) for AI/LLM consumption.