Esta versão do projeto implementa a leitura de retorno de boletos de uma forma mais simples utilizando programação funcional no Java 8+. Com tais recursos, precisamos criar menos classes para fornecer uma implementação do padrão Strategy.

A implementação é baseada no diagrama a seguir:

strategy base funcional class diagram

Detalhes de Implementação

Ao criar uma implementação funcional para o padrão Strategy, além de reduzir o número de classes que temos que criar, depois de entender os conceitos de programação funcional, perceba que a essência de como implementar o padrão não muda.

Usando a implementação puramente orientada a objetos, a classe ProcessadorBoletos possui um código como:

public class ProcessarBoletos {
    private LeituraRetorno leituraRetorno;

    public final void processar(String nomeArquivo){
        List<Boleto> boletos = leituraRetorno.lerArquivo(nomeArquivo);
        for (Boleto boleto : boletos) {
            System.out.println(boleto);
        }
    }
}

Já a mesma classe no projeto funcional possui a seguinte implementação de tal classe:

public class ProcessarBoletos {
    private Function<String, List<Boleto>> leituraRetorno;

    public void processar(String nomeArquivo){
        List<Boleto> boletos = leituraRetorno.apply(nomeArquivo);
        for (Boleto boleto : boletos) {
            System.out.println(boleto);
        }
    }
}

Observe que o código é praticamente o mesmo, só muda que na primeira implementação temos um atributo leituraRetorno do tipo LeituraRetorno, esta uma interface que possui um método lerArquivo(). Já na implementação funcional, a estratégia é definida por meio de um atributo de mesmo nome, mas do tipo Function, que armazena a implementação (a função) a ser utilizada para ler de fato o arquivo. Function é o que chamamos de interface funcional a partir do Java 8. Como ela não foi definida por nós, ela já possui um método definido, chamado apply. Assim, internamente, o método processar da classe estrategista (ProcessadorBoletos) apenas chama um método diferente na primeira linha dos métodos processar nos exemplos acima.