🏭 O que é?

O Factory Method é um padrão de projeto do tipo criacional.

Seu principal objetivo é delegar a responsabilidade de instanciar objetos para uma classe terceira (a Factory), com base em uma condição específica.

Isso promove maior flexibilidade, baixo acoplamento e facilita a manutenção e evolução da aplicação.


💡 Exemplo:

Vamos considerar uma aplicação que gerencia pedidos. Um pedido pode passar por diversas etapas, como:

  • PENDENTE
  • PAGAMENTO
  • EM ENTREGA
  • ENTREGUE

Com base nessas etapas, podemos criar diferentes implementações para tratar o comportamento de cada status.

A Factory será responsável por retornar a implementação correta com base no status atual do pedido.

🧱 Exemplo da Factory:

@Component
public class OrderProcessorFactory {

    private final List<OrderProcessorService> processors;

    public OrderProcessorFactory(List<OrderProcessorService> processors) {
        this.processors = processors;
    }

    public OrderProcessorService getProcessor(String status) {
        return processors.stream()
                .filter(processor -> processor.isStatus(status))
                .findFirst()
                .orElseThrow(() -> new InvalidDataException("Nenhum processador disponível para o status: " + status));
    }
}

Neste exemplo, a Factory percorre a lista de implementações disponíveis (processors) e seleciona aquela que suporta o status informado, utilizando o método isStatus.

@Service
public class CreateOrderServiceImpl implements OrderProcessorService {

    private final CalculateOrderPriceService calculateOrderPrice;

    public CreateOrderServiceImpl(CalculateOrderPriceService calculateOrderPrice) {
        this.calculateOrderPrice = calculateOrderPrice;
    }

    @Override
    public OrderEntity processor(OrderEntity order) {
        BigDecimal totalPrice = calculateOrderPrice.calculate(order.getItems());
        order.setTotalPrice(totalPrice);
        order.setStatus(OrderStatusEnum.CREATED.getCode());
        return order;
    }

    @Override
    public boolean isStatus(String status) {
        return StringUtils.hasLength(status) && status.equals(OrderStatusEnum.PENDING.getCode());
    }
}

A classe acima representa uma etapa específica do pedido.
O método isStatus é usado pela Factory para verificar se esta implementação é compatível com o status recebido.