Especialização em Sistemas com Java 21 LTS • Capítulo 10


🎯 Visão Geral dos Exemplos Práticos

Neste laboratório prático, implementaremos exemplos corporativos completos explorando:

  1. Contratos com Métodos Default e Privados: enriquecimento de interfaces com comportamentos de retentativa e validações internas.
  2. Implementações Concretas Polimórficas: processamento especializado via PIX e Cartão de Crédito com juros de parcelamento.
  3. Padrão Inversão de Controle (IoC): desacoplamento de serviços de negócio que dependem exclusivamente de contratos de interface.

💻 Exemplo 01 — Gateway de Pagamentos Unificado com Métodos Default e Privados

package com.empresa.contratos;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
import java.util.UUID;

/**
 * Contrato moderno de serviços de pagamento com tolerância a falhas.
 */
public class GatewayPagamentoLaboratorio {

    public record Comprovante(String idTransacao, boolean sucesso, String mensagem, BigDecimal valorEfetivo) {}

    public interface GatewayPagamento {
        // Métodos abstratos do contrato
        Comprovante debitar(BigDecimal valor, String identificadorPagador);
        boolean estornar(String idTransacao);

        // Método default com lógica de retentativa
        default Comprovante debitarComRetry(BigDecimal valor, String identificador, int tentativasMaximas) {
            validarRequisicao(valor, identificador); // Método privado da interface

            for (int tentativa = 1; tentativa <= tentativasMaximas; tentativa++) {
                try {
                    System.out.printf("   [TENTATIVA %d/%d] Comunicando com o terminal financeiro...%n", tentativa, tentativasMaximas);
                    Comprovante res = debitar(valor, identificador);
                    if (res.sucesso()) {
                        return res;
                    }
                } catch (Exception e) {
                    System.out.printf("   ⚠️ Falha de comunicação na tentativa %d: %s%n", tentativa, e.getMessage());
                }
            }
            return new Comprovante("FAIL-TIMEOUT", false, "Operação excedeu o limite de tentativas", valor);
        }

        // Método estático utilitário de conveniência
        static void registrarAuditoria(Comprovante comprovante) {
            System.out.printf("   📋 [LOG AUDITORIA] Transação: %s | Status: %s | Valor: R$ %.2f%n",
                    comprovante.idTransacao(), comprovante.sucesso() ? "OK" : "RECUSADA", comprovante.valorEfetivo());
        }

        // Método privado para reuso entre métodos default (Java 9+)
        private void validarRequisicao(BigDecimal valor, String identificador) {
            Objects.requireNonNull(valor, "Valor da transação não pode ser nulo.");
            Objects.requireNonNull(identificador, "Identificador do pagador obrigatório.");
            if (valor.compareTo(BigDecimal.ZERO) <= 0) {
                throw new IllegalArgumentException("Valor da transação deve ser positivo.");
            }
        }
    }

    public static class GatewayPix implements GatewayPagamento {
        @Override
        public Comprovante debitar(BigDecimal valor, String chavePix) {
            String txId = "PIX-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
            System.out.printf("⚡ [PIX] Pagamento instantâneo confirmado para a chave: %s%n", chavePix);
            return new Comprovante(txId, true, "LIQUIDADO_INSTANTANEO", valor);
        }

        @Override
        public boolean estornar(String idTransacao) {
            System.out.printf("⚡ [PIX] Devolução de R$ estornada com sucesso para %s%n", idTransacao);
            return true;
        }
    }

    public static class GatewayCartaoCredito implements GatewayPagamento {
        private final int parcelas;

        public GatewayCartaoCredito(int parcelas) {
            this.parcelas = Math.max(1, parcelas);
        }

        @Override
        public Comprovante debitar(BigDecimal valor, String numeroCartao) {
            String txId = "CC-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
            BigDecimal taxaJuros = (parcelas > 1) ? new BigDecimal("0.025").multiply(new BigDecimal(parcelas)) : BigDecimal.ZERO;
            BigDecimal valorComJuros = valor.add(valor.multiply(taxaJuros)).setScale(2, RoundingMode.HALF_UP);

            System.out.printf("💳 [CARTÃO] Débito autorizado em %dx de R$ %.2f (Total com encargos: R$ %.2f)%n",
                    parcelas, valorComJuros.divide(new BigDecimal(parcelas), 2, RoundingMode.HALF_UP), valorComJuros);

            return new Comprovante(txId, true, "AUTORIZADO_BANDEIRA", valorComJuros);
        }

        @Override
        public boolean estornar(String idTransacao) {
            System.out.printf("💳 [CARTÃO] Chargeback processado para %s%n", idTransacao);
            return true;
        }
    }

    // Serviço cliente que pratica Injeção de Dependências
    public static class ServicoCobranca {
        private final GatewayPagamento gateway;

        public ServicoCobranca(GatewayPagamento gateway) {
            this.gateway = gateway;
        }

        public Comprovante processarFatura(BigDecimal total, String idCliente) {
            Comprovante comp = gateway.debitarComRetry(total, idCliente, 3);
            GatewayPagamento.registrarAuditoria(comp);
            return comp;
        }
    }

    public static void main(String[] args) {
        System.out.println("================================================================================");
        System.out.println("            SIMULADOR DE CHECKOUT COM INVERSÃO DE CONTROLE (JAVA 21)            ");
        System.out.println("================================================================================");

        // Cenário 1: Pagamento via PIX
        System.out.println("--- 1. Processamento via Provedor PIX ---");
        ServicoCobranca cobrancaPix = new ServicoCobranca(new GatewayPix());
        cobrancaPix.processarFatura(new BigDecimal("350.00"), "contato@cliente.com.br");

        // Cenário 2: Pagamento via Cartão de Crédito em 3x
        System.out.println("\n--- 2. Processamento via Provedor Cartão (3 Parcelas) ---");
        ServicoCobranca cobrancaCartao = new ServicoCobranca(new GatewayCartaoCredito(3));
        cobrancaCartao.processarFatura(new BigDecimal("1200.00"), "****.****.****.4920");

        System.out.println("================================================================================");
    }
}

📋 Resultado Esperado no Console

================================================================================
            SIMULADOR DE CHECKOUT COM INVERSÃO DE CONTROLE (JAVA 21)            
================================================================================
--- 1. Processamento via Provedor PIX ---
   [TENTATIVA 1/3] Comunicando com o terminal financeiro...
⚡ [PIX] Pagamento instantâneo confirmado para a chave: contato@cliente.com.br
   📋 [LOG AUDITORIA] Transação: PIX-8A4F1D90 | Status: OK | Valor: R$ 350.00

--- 2. Processamento via Provedor Cartão (3 Parcelas) ---
   [TENTATIVA 1/3] Comunicando com o terminal financeiro...
💳 [CARTÃO] Débito autorizado em 3x de R$ 430.00 (Total com encargos: R$ 1290.00)
   📋 [LOG AUDITORIA] Transação: CC-10B5E2C4 | Status: OK | Valor: R$ 1290.00
================================================================================