Publicación: 5 months
El patrón de diseño Composición permite que los objetos se compongan en estructuras de árbol para representar jerarquías de parte-todo. Este patrón trata de individuos y sus composiciones de forma uniforme.
“Design Patterns: Elements of Reusable Object-Oriented Software" por Erich Gamma, Richard Helm, Ralph Johnson, y John Vlissides (1994)
1: public Payment paidService(Payment payment) { 2: validarTipoServicio(payment); 3: validarTipoMoneda(payment); 4: 5: var saldo = validarSaldoCliente(payment); 6: if(payment.getAmount() > saldo) { 7: throw new UnprocessableEntityException("No tiene el saldo suficiente para realizar un pago de servicio"); 8: } 9: 10: var pagoServicioTerceroRes = realizarPagoServicioTercero(payment); 11: 12: sincronizarPagoConPagoServicioTerceroRes(pagoServicioTerceroRes); 13: 14: return payment; 15: }
1: public Payment paidService(Payment payment) { log.info("inicio del pago “ + payment); log.info("inicio de validarTipoServicio “ + payment); 2: validarTipoServicio(payment); log.info("fin de validarTipoServicio “ + payment); log.info("inicio de validarTipoMoneda “ + payment); 3: validarTipoMoneda(payment); log.info("fin de validarTipoMoneda “ + payment); 4: log.info("inicio de validarSaldoCliente “ + payment); 5: var saldo = validarSaldoCliente(payment); log.info("fin de validarSaldoCliente “ + payment); 6: if(payment.getAmount() > saldo) { 7: throw new UnprocessableEntityException("No tiene el saldo suficiente para realizar un pago de servicio"); 8: } 9: log.info("inicio de realizarPagoServicioTercero “ + payment); 10: var pagoServicioTerceroRes = realizarPagoServicioTercero(payment); log.info("fin de realizarPagoServicioTercero “ + payment); 11: log.info("fin de sincronizarPagoConPagoServicioTerceroRes “ + payment); 12: sincronizarPagoConPagoServicioTerceroRes(pagoServicioTerceroRes); log.info("inicio de sincronizarPagoConPagoServicioTerceroRes “ + payment); 13: log.info("fin del pago “ + payment); 14: return payment; 15: }
1: public Payment paidService(Payment payment) { log.info("inicio del pago “ + payment); log.info("inicio de validarTipoServicio “ + payment); 2: validarTipoServicio(payment); log.info("fin de validarTipoServicio “ + payment); log.info("inicio de validarTipoMoneda “ + payment); 3: validarTipoMoneda(payment); log.info("fin de validarTipoMoneda “ + payment); 4: log.info("inicio de validarSaldoCliente “ + payment); 5: var saldo = validarSaldoCliente(payment); log.info("fin de validarSaldoCliente “ + payment); 6: if(payment.getAmount() > saldo) { 7: throw new UnprocessableEntityException("No tiene el saldo suficiente para realizar un pago de servicio"); 8: } 9: log.info("inicio de realizarPagoServicioTercero “ + payment); 10: var pagoServicioTerceroRes = realizarPagoServicioTercero(payment); log.info("fin de realizarPagoServicioTercero “ + payment); log.info("inicio de notificaciónPagoAlServicioSaldos “ + pagoServicioTerceroRes); var pagoServicioTerceroRes = notificaciónPagoAlServicioSaldos(pagoServicioTerceroRes); log.info("fin de notificaciónPagoAlServicioSaldos “ + pagoServicioTerceroRes); 11: log.info("fin de sincronizarPagoConPagoServicioTerceroRes “ + payment); 12: sincronizarPagoConPagoServicioTerceroRes(pagoServicioTerceroRes); log.info("inicio de sincronizarPagoConPagoServicioTerceroRes “ + payment); 13: log.info("fin del pago “ + payment); 14: return payment; 15: }
Component. Define una interfaz para los objetos que pueden ser compuestos. Declara una interfaz para acceder y manejar los hijos de los objetos compuestos.
Leaf. Representa los objetos que no tienen hijos. Una Leaf realiza el comportamiento definido en la interfaz Component.
Composite. Define un comportamiento para los componentes que tienen hijos y almacena dichos hijos. Implementa las operaciones relacionadas con los hijos en la interfaz Component.
Autor: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software (1994).
// Component interface PaymentServiceOperation { Object execute(); } // Composite class PaidProcess { private static final Logger logger = LoggerFactory.getLogger(PaidServiceProcess.class); private final List<AbstractPaymentOperation> operations = new ArrayList<>(); public void addOperation(AbstractPaymentOperation operation) { operations.add(operation); } public void execute(Payment payment, Object data) { logger.info("Starting paid service process for payment ID: {}", payment.getId()); try { for (AbstractPaymentOperation operation : operations) { logger.info("Executing operation: {}", operation.getClass().getName()); operation.setPayment(payment); data = operation.execute(data); } } finally { paymentRepository.save(payment); logger.info("Api apiRequest saved: {}", payment.getId()); } } }
// Leaf class ValidarTipoServicio extends AbstractPaymentOperation { @Override public Object execute(Object data) { return new Object(); } } class ValidarTipoMoneda extends AbstractPaymentOperation { @Override public Object execute(Object data) { return new Object(); } } class ValidarSaldoCliente extends AbstractPaymentOperation { @Override public Object execute(Object data) { return new Object(); } } class RealizarPagoServicioTercero extends AbstractPaymentOperation { @Override public Object execute(Object data) { return new Object(); } } class NotificacionPagoAlServicioSaldos extends AbstractPaymentOperation { @Override public Object execute(Object data) { return new Object(); } } class SincronizarPagoConPagoServicioTerceroRes extends AbstractPaymentOperation { @Override public Object execute(Object data) { if (!(data instanceof PagoServicioTerceroDto)) { throw new IllegalArgumentException("Invalid data type for SincronizarPagoConPagoServicioTerceroRes"); } return new Object(); } } // Esta clase es extra, la ocupamos para mantener accesible el Payment a través de todo el proceso abstract class AbstractPaymentOperation implements PaymentServiceOperation { protected Payment payment; }
public Payment paidService(Payment payment) { var paidProcess = new PaidProcess(); paidProcess.addOperation(new ValidarTipoServicio()); paidProcess.addOperation(new ValidarTipoMoneda()); paidProcess.addOperation(new ValidarSaldoCliente()); paidProcess.addOperation(new RealizarPagoServicioTercero()); paidProcess.addOperation(new NotificacionPagoAlServicioSaldos()); paidProcess.addOperation(new SincronizarPagoConPagoServicioTerceroRes()); // Si es necesario inicializar el proceso con algún valor. paidProcess.execute(payment, null); return payment; }