fbpx

PATRÓN de DISEÑO FACTORY en JAVA

El patrón de diseño Factory es uno de los patrones de diseño más comunes y útiles en Java. Se utiliza para crear objetos de una clase determinada sin necesidad de conocer el código específico de esa clase. En lugar de crear directamente una instancia de una clase, se utiliza un método factory para crear el objeto.

Un ejemplo típico de uso del patrón de diseño Factory es cuando tenemos una aplicación que necesita crear diferentes tipos de objetos en función de una entrada del usuario o de un archivo de configuración. En lugar de tener que escribir código específico para cada tipo de objeto, podemos utilizar una fábrica para crear los objetos necesarios.

Para implementar el patrón de diseño Factory en Java, necesitamos crear una interfaz que defina el método factory y luego crear una clase concreta que implemente esa interfaz. La clase concreta se encargará de crear los objetos necesarios.

Problema

Recapitulemos, eres programador, como programador te encantan las condiciones, desde que empezaste a programar es lo primero que aprendiste. Pero luego ves algo como esto:

public void createPayment(PaymentType paymentType) {
    if (paymentType == PaymentType.CREDIT_CARD) {
        createCreditCardPayment();
        // More code here
    } else if (paymentType == PaymentType.PAYPAL) {
        createPaypalPayment();
        // More code here
    } else if (paymentType == PaymentType.DIRECT_DEBIT) {
        createDirectDebitPayment();
        // More code here
    } else if (paymentType == PaymentType.DEBIT_CARD) {// More code here
        createDebitCardPayment();
        // More code here
    } else if (paymentType == PaymentType.BITCOIN) {// More code here
        createBitcoinPayment();
        // More code here
    } else if (paymentType == PaymentType.CASH) {// More code here
        createCashPayment();
        // More code here
    } else if (paymentType == PaymentType.APPLE_PAY) {// More code here
        createApplePayPayment();
        // More code here
    } else if (paymentType == PaymentType.GOOGLE_PAY) {// More code here
        createGooglePayPayment();
        // More code here
    } else {
        throw new NoSuchMethodException("Payment not found");
    }
}

Wow, quiero decir, cuántos if y else hay, y luego cada método dentro de la clase lo hace más grande. Buena suerte para depurarlo y verificar en qué línea puede tener problemas, o si necesita hacer algunos cambios.

Una solución que se le puede ocurrir es usar la condición de cambio…

public void createPayment(PaymentType paymentType) {
    switch (paymentType) {
        case CREDIT_CARD:
            // More code here
            createCreditCardPayment();
            // More code here
            break;
        case PAYPAL:
            // More code here
            createPaypalPayment();
            // More code here
            break;
        case DIRECT_DEBIT:
            // More code here
            createDirectDebitPayment();
            // More code here
            break;
        case DEBIT_CARD:
            // More code here
            createDebitCardPayment();
            // More code here
            break;
        case BITCOIN:
            // More code here
            createBitcoinPayment();
            // More code here
            break;
        case CASH:
            // More code here
            createCashPayment();
            // More code here
            break;
        case APPLE_PAY:
            // More code here
            createApplePayPayment();
            // More code here
            break;
        case GOOGLE_PAY:
            // More code here
            createGooglePayPayment();
            // More code here
            break;
        default:
            throw new NoSuchMethodException("Payment not found");
    }
}

Bueno… para ser honesto, realmente no resuelve tanto, en realidad, necesitarías incluso unas pocas líneas de código más debido al “break”.

Solución: Patrón de diseño Factory

Necesitamos delegar la función a una clase diferente que se encargue de cada pago individual o también más funciones que se deben hacer.

Allí necesitamos crear una interfaz para que cada clase implemente nuestra funcionalidad requerida.

public interface Pago {
    void crearPago();
}

Además de ello necesitaremos identificar que clase esta identificada con qué tipo de clase delegada. Es por eso que necesitamos crear la clase de fábrica.

public class PagoFactory {
    private final static Map<TipoDePago, Pago> pagos = new HashMap<>(){{
        put(TipoDePago.PAYPAL, new PagoPayPal());
        put(TipoDePago.TARJETA_CREDITO, new PagoTarjetaCredito());
        put(TipoDePago.TARJETA_DEBITO, new PagoTarjetaDebito());
        put(TipoDePago.TRANSFERENCIA_BANCARIA, new PagoTransferenciaBancaria());
        put(TipoDePago.BITCOIN, new PagoBitcoin());
        put(TipoDePago.EFECTIVO, new PagoEfectivo());
        put(TipoDePago.APPLE_PAY, new PagoApplePay());
        put(TipoDePago.GOOGLE_PAY, new PagoGooglePay());
    }};

    public Pago obtenerPago(TipoDePago tipoDePago) {
        return pagos.get(tipoDePago);
    }

}

Y por último tenemos que juntarlo todo y podremos obtener el resultado dependiendo de nuestro tipo de pago:

public class Main {

    public static void main(String[] args) {
        PagoFactory pagoFactory = new PagoFactory();
        Pago pago = pagoFactory.obtenerPago(TipoDePago.TARJETA_CREDITO);
        pago.crearPago();
    }

}