El patrón Composite permite que los clientes traten a objetos individuales y composiciones de objetos de manera uniforme. Esto se logra mediante la creación de una interfaz común para componentes individuales y compuestos.
Ejemplo de Composite en Java:
Supongamos que tienes una interfaz Componente
que define operaciones comunes para componentes individuales y compuestos:
// Interfaz Componente
interface Componente {
void operacion();
}
Y tienes dos implementaciones: Hoja
(componente individual) y Compuesto
(componente que contiene otros componentes):
// Hoja (Componente individual)
class Hoja implements Componente {
private String nombre;
public Hoja(String nombre) {
this.nombre = nombre;
}
@Override
public void operacion() {
System.out.println("Operación en Hoja " + nombre);
}
}
// Compuesto (Componente que contiene otros componentes)
class Compuesto implements Componente {
private List<Componente> componentes = new ArrayList<>();
public void agregar(Componente componente) {
componentes.add(componente);
}
public void eliminar(Componente componente) {
componentes.remove(componente);
}
@Override
public void operacion() {
System.out.println("Operación en Compuesto");
for (Componente componente : componentes) {
componente.operacion();
}
}
}
Ahora puedes utilizar estas clases para crear estructuras complejas:
public class Principal {
public static void main(String[] args) {
// Crear hojas individuales
Hoja hoja1 = new Hoja("Hoja 1");
Hoja hoja2 = new Hoja("Hoja 2");
// Crear un compuesto y agregar hojas
Compuesto compuesto = new Compuesto();
compuesto.agregar(hoja1);
compuesto.agregar(hoja2);
// Crear otra hoja individual
Hoja hoja3 = new Hoja("Hoja 3");
// Crear un compuesto y agregar la hoja individual y el compuesto anterior
Compuesto compuestoPrincipal = new Compuesto();
compuestoPrincipal.agregar(hoja3);
compuestoPrincipal.agregar(compuesto);
// Llamar a operaciones
compuestoPrincipal.operacion();
}
}
Cuándo usar el patrón Composite:
- Tratar Componentes Individuales y Compuestos de Forma Uniforme:
- Cuando necesitas tratar tanto componentes individuales como compuestos de manera uniforme.
- Composición Recursiva:
- Cuando la estructura de tus objetos puede ser representada como una composición anidada de objetos más pequeños.
- Clientes Independientes de la Estructura de la Jerarquía:
- Para permitir que los clientes manipulen tanto hojas como compuestos sin conocer la estructura interna de la jerarquía.
- Simplificar la Interfaz del Cliente:
- Cuando deseas simplificar la interfaz del cliente al no tener que distinguir entre componentes individuales y compuestos.
El patrón Composite es especialmente útil en situaciones donde necesitas tratar colecciones de objetos de manera uniforme, independientemente de si son objetos individuales o compuestos. Proporciona una estructura jerárquica que simplifica la manipulación de estos elementos.