Composite Entity
También conocido como
- Coarse-Grained Entity
Propósito
El patrón de diseño Entidad Compuesta tiene como objetivo gestionar un conjunto de objetos persistentes
interrelacionados como si fueran una única entidad. Se utiliza comúnmente en el contexto de Enterprise JavaBeans (EJB) y
marcos empresariales similares para representar estructuras de datos basadas en gráficos dentro de modelos de negocio,
permitiendo a los clientes tratarlos como una sola unidad.
Explicación
Ejemplo real
En una consola, puede haber muchas interfaces que necesiten ser gestionadas y controladas. Usando el patrón de entidad
compuesta, objetos dependientes como mensajes y señales pueden ser combinados y controlados usando un único objeto.
En palabras sencillas
El patrón de entidad compuesta permite representar y gestionar un conjunto de objetos relacionados mediante un objeto
unificado.
Ejemplo programático
Necesitamos una solución genérica para el problema. Para ello, vamos a introducir un patrón genérico de entidad
compuesta.
public abstract class DependentObject<T> {
T data;
public void setData(T message) {
this.data = message;
}
public T getData() {
return data;
}
}
public abstract class CoarseGrainedObject<T> {
DependentObject<T>[] dependentObjects;
public void setData(T... data) {
IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));
}
public T[] getData() {
return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();
}
}
La entidad compuesta especializada consola
hereda de esta clase base de la siguiente manera.
public class MessageDependentObject extends DependentObject<String> {
}
public class SignalDependentObject extends DependentObject<String> {
}
public class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {
@Override
public String[] getData() {
super.getData();
return new String[] {
dependentObjects[0].getData(), dependentObjects[1].getData()
};
}
public void init() {
dependentObjects = new DependentObject[] {
new MessageDependentObject(), new SignalDependentObject()};
}
}
public class CompositeEntity {
private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();
public void setData(String message, String signal) {
console.setData(message, signal);
}
public String[] getData() {
return console.getData();
}
}
Gestionando ahora la asignación de objetos mensaje y señal con la entidad compuesta consola
.
var console=new CompositeEntity();
console.init();
console.setData("No Danger","Green Light");
Arrays.stream(console.getData()).forEach(LOGGER::info);
console.setData("Danger","Red Light");
Arrays.stream(console.getData()).forEach(LOGGER::info);
Diagrama de clases
Aplicabilidad
- Útil en aplicaciones empresariales donde los objetos de negocio son complejos e involucran varios objetos
interdependientes. - Ideal para escenarios donde los clientes necesitan trabajar con una interfaz unificada para un conjunto de objetos en
lugar de entidades individuales. - Aplicable en sistemas que requieren una vista simplificada de un modelo de datos complejo para clientes o servicios
externos.
Usos conocidos
- Aplicaciones empresariales con modelos de negocio complejos, particularmente aquellas que utilizan EJB o marcos
empresariales similares. - Sistemas que requieren abstracción sobre esquemas de bases de datos complejos para simplificar las interacciones con
los clientes. - Aplicaciones que necesitan reforzar la consistencia o las transacciones a través de múltiples objetos en una entidad
de negocio.
Consecuencias
Ventajas:
- Simplifica las interacciones del cliente con modelos de entidad complejos proporcionando una interfaz unificada.
- Mejora la reutilización y el mantenimiento de la capa de negocio al desacoplar el código del cliente de los complejos
componentes internos de las entidades de negocio. - Facilita la gestión de transacciones y la aplicación de la coherencia en un conjunto de objetos relacionados.
Contrapartidas:
- Puede introducir un nivel de indirección que podría afectar al rendimiento.
- Puede dar lugar a interfaces de grano demasiado grueso que podrían no ser tan flexibles para todas las necesidades de
los clientes. - Requiere un diseño cuidadoso para evitar entidades compuestas hinchadas que sean difíciles de gestionar.
Patrones relacionados
- Decorador: Para añadir dinámicamente comportamiento a objetos
individuales dentro de la entidad compuesta sin afectar a la estructura. - Fachada: Proporciona una interfaz simplificada a un subsistema
complejo, de forma similar a como una entidad compuesta simplifica el acceso a un conjunto de objetos. - Flyweight: Útil para gestionar objetos compartidos dentro de
una entidad compuesta para reducir la huella de memoria.