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:

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.