Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

Não saberia implementar

Eu não entendi muito bem como seria a implementação usando o Chain Of Responsability e o Decorator. Alguém consegue demonstrar?

9 respostas

Oi Vinicius! Tudo bem?

Vou tentar ajudar.

Como é explicado no curso, para saber aplicar um pattern você deve saber para que serve e qual situação se aplica.

Vamos começar com o mais simples: Decorator

Decorator recebe um objeto em seu construtor e oferece métodos que o objeto original não possui.

Pessoa.java

public class Pessoa {
    private String nome;
    private String sobrenome;
    private String titulo;

    /* ... getters e setters omitidos ... */
}

PessoaDecorator

public class PessoaDecorator {
    private Pessoa pessoa;

    PessoaDecorator(Pessoa pessoa){
        this.pessoa = pessoa;
    }

    public String getNomeCompleto(){
        return pessoa.getNome() + " " + pessoa.getSobrenome();
    }

    public String getNomeCompletoETitulo(){
        return pessoa.getTitulo() + " " + pessoa.getNome() + " " + pessoa.getSobrenome();
    }
}

Bom, decorator é bem isso.

Agora quando precisar do nome completo em alguma parte do seu código, basta usar o decorator criado através de sua instancia de Pessoa.

Vamos continuar com o chain of responsibility....

Chain of Responsability (CoR) é um padrão que exige um pouco mais de conhecimento.

Entenda a palavra chain como uma corrente, sendo cada um dos elos dessa corrente uma ação que precisa ser realizada.

A execução só termina quando a chain chegou ao seu fim, ou seja, não tem mais elos por ser chamado.

Vou descrever com um exemplo bem simples, que são impostos no Brasil. Temos impostos desde municipais, como estaduais e federais.

Teríamos em nossa corrente, 3 nós, um que saberia calcular impostos municipais, outro estaduais e outro federal. Ao fim da chamada dos três nós o tributo completo está calculado.

O método de todas as classes CoR recebe sempre o mesmo tipo de dados no seu método execute. Por isso criamos uma interface para o CoR.

Agora... imagina um pedido.... comprou produtos... Ele iniciaria o CoR no primeiro elo, recebendo um pedido e o total de impostos.

E elo ImpostosMunicipais verificaria quais impostos aplicam na esfera municipal a cada produto e seus valores. calcularia o total de impostos municipais e verificaria se existe um próximo elo. Existe o estadual! Então ele o chamará.

E elo ImpostosEstaduais verificaria quais impostos aplicam na esfera estadual a cada produto e seus valores. calcularia o total de impostos estaduais e verificaria se existe um próximo elo. Existe o federal! Então ele o chamará.

E elo ImpostosFederal verificaria quais impostos aplicam na esfera federal a cada produto e seus valores. calcularia o total de impostos federais e verificaria se existe um próximo elo. Não existe! A cadeia se completou.

Dessa maneira entendemos que para o cenário didático e fictício de impostos, são necessárias três execuções com responsabilidades diferentes para cumprir com os cálculos de impostos.

Espero ter ajudado,

Qualquer dúvida, estou à disposição,

Abraço e sucesso,

Rodrigo

Acho que consegui implementar uma solução usando o Chain of Responsability com Template Method. Graças a sua explicação tive um melhor entendimento do que fazer!

Muito obrigado mesmo! :D O que acha deste algoritmo?

public abstract class AbstractFilter {

private AbstractFilter nextFilter;

boolean removeFatura(Fatura fatura){
    if(condicaoEliminar(fatura)) {
        return true;
    }

    if(nextFilter != null) {
        return nextFilter.removeFatura(fatura);
    }

    return false;
}

protected void setProximo(AbstractFilter filter){
    this.nextFilter = filter;
}

abstract boolean condicaoEliminar(Fatura fatura);

}

Oi Vinicius! Tudo bem?

Show! Sua implementação da classe abstrata está correta estruturalmente falando.

Poderia compartilhar comigo as implementações dessa classe para que eu possa analizar as responsabilidades e te dizer se está correto?

Fico no aguardo,

Abraço e sucesso,

Rodrigo

Claro! Seguem as classes...

import java.util.ArrayList; import java.util.List;

public class FiltroFaturaExecutor {

public static List<Fatura> filtarFaturas(List<Fatura> faturas) {
    //Método grande e acoplado para facilitar leitura para aprendizado

    List<Fatura> novaListaFatura = new ArrayList<>();

    AbstractFilter f1 = new MenorDoisMil();
    AbstractFilter f2 = new MaiorOitoMil();
    AbstractFilter f3 = new RegraSP();

    f1.setProximo(f2);
    f2.setProximo(f3);

    for (Fatura fatura : faturas) {
        if (!f1.removeFatura(fatura)) {
            novaListaFatura.add(fatura);
        }
    }

    return novaListaFatura;
}

}

public class Main {
    public static void main(String[] args) {
        List<Fatura> faturas = new ArrayList<>();

        faturas.add(new Fatura(1000, "MG")); //Deve ser eliminada
        faturas.add(new Fatura(2000, "RJ"));
        faturas.add(new Fatura(3000, "AM"));
        faturas.add(new Fatura(4000, "SP")); //Deve ser eliminada
        faturas.add(new Fatura(5000, "MG"));
        faturas.add(new Fatura(7000, "RJ"));
        faturas.add(new Fatura(8000, "AM"));
        faturas.add(new Fatura(9000, "RS")); //Deve ser eliminada
        faturas.add(new Fatura(10000, "PR")); //Deve ser eliminada

        faturas = FiltroFaturaExecutor.filtarFaturas(faturas);

        for (Fatura fatura : faturas) {
            System.out.println("Valor: " + fatura.getValor() + " - Origem: " + fatura.getEstadoOrigem());
        }
    }
}
public class MaiorOitoMil extends AbstractFilter {
    @Override
    boolean condicaoEliminar(Fatura fatura) {
        return fatura.getValor() > 8000.00;
    }
}

public class MenorDoisMil extends AbstractFilter {
    @Override
    boolean condicaoEliminar(Fatura fatura) {
        return fatura.getValor() < 2000.00;
    }
}

public class RegraSP extends AbstractFilter {
    @Override
    boolean condicaoEliminar(Fatura fatura) {
        return fatura.getValor() > 3000.00 && fatura.getValor() < 4500.00 && fatura.getEstadoOrigem().equals("SP");
    }
}
solução!

Oi Vinicius,

Está bem implementado tanto tecnicamente quanto funcional.

Parabéns, brother!

Abraço,

Rodrigo

Haaa muito obrigado!! :D