Fiz uma refatoração no código do instrutor no desafio Sistema de pagamentos para utilizar o design pattern Strategy & Simple Factory, parando para analisar que, em uma startup ou empresa real, esses métodos de pagamento poderiam crescer e surgir novas formas de se efetuar o pagamento. Desta forma, o client tem de estar ciente das estratégias para saber qual se aplica a ele e, também, desta forma, a aplicação fica mais escalável e propícia a testes, já que posso gerenciar manualmente cada uma sem necessitar das instâncias diretamente, o que deixaria o código fortemente acoplado e dificil para manutenção.
Class Main
package org.maelys.strategy;
import org.maelys.strategy.factory.PaymentFactory;
import org.maelys.strategy.service.Payment;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Payment payment = new Payment();
var type = PaymentFactory.getPayment("CreditCard");
payment.setPaymentInterface(type);
BigDecimal result = payment.calculate(new BigDecimal("100000"));
System.out.println(result);
payment.confirmPayment(result);
}
}
Class PaymentFactory
package org.maelys.strategy.factory;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.maelys.strategy.service.PaymentInterface;
import org.maelys.strategy.service.internal.Boleto;
import org.maelys.strategy.service.internal.CreditCard;
import org.maelys.strategy.service.internal.Pix;
public class PaymentFactory {
@Contract("_ -> new")
public static @NotNull PaymentInterface getPayment(@NotNull String paymentType) {
switch (paymentType) {
case "Boleto" -> {
return new Boleto();
}
case "Pix" -> {
return new Pix();
}
case "CreditCard" -> {
return new CreditCard();
}
default -> throw new IllegalStateException("Unexpected value: " + paymentType);
}
}
}
Class Payment
package org.maelys.strategy.service;
import java.math.BigDecimal;
import java.text.DecimalFormat;
@lombok.AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@lombok.NoArgsConstructor(access = lombok.AccessLevel.PUBLIC)
public class Payment {
@lombok.Setter(value = lombok.AccessLevel.PUBLIC)
private PaymentInterface paymentInterface;
public void confirmPayment(BigDecimal amount) {
DecimalFormat formatter = new DecimalFormat("R$ #,###0.00");
System.out.printf("Payment of %s confirmed%n", formatter.format(amount));
}
public BigDecimal calculate(BigDecimal amount) {
return paymentInterface.calculate(amount);
}
}
Interface PaymentInterface
package org.maelys.strategy.service;
import java.math.BigDecimal;
@FunctionalInterface
public interface PaymentInterface {
BigDecimal calculate(BigDecimal amount);
}
Class Pix
package org.maelys.strategy.service.internal;
import org.maelys.strategy.service.PaymentInterface;
import java.math.BigDecimal;
public class Pix implements PaymentInterface {
@Override
public BigDecimal calculate(BigDecimal amount) {
return BigDecimal.ZERO;
}
}
Class CreditCard
package org.maelys.strategy.service.internal;
import org.jetbrains.annotations.NotNull;
import org.maelys.strategy.service.PaymentInterface;
import java.math.BigDecimal;
public class CreditCard implements PaymentInterface {
@Override
public BigDecimal calculate(@NotNull BigDecimal amount) {
return amount.multiply(new BigDecimal("0.03"));
}
}
Class Boleto
package org.maelys.strategy.service.internal;
import org.jetbrains.annotations.NotNull;
import org.maelys.strategy.service.PaymentInterface;
import java.math.BigDecimal;
public class Boleto implements PaymentInterface {
@Override
public BigDecimal calculate(@NotNull BigDecimal amount) {
return amount.multiply(new BigDecimal("0.01"));
}
}