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

Duvida na resolução de um problema na aula OCP / DIP

Maurício,

Entendi perfeitamente os conceitos passados nesta aula, porém como existe a regra de valor de frete por cidades, travei no seguinte problema:

Resolvi criar a interface Cidade para implementar as classes Rio de Janeiro, São Paulo e etc.

Referente aos IFs da tabela de preços, consegui refatorar usando o pattern Chain of Responsability, onde Criei as classes MaiorQueMil e MaiorCincoMil realizando a primeira regra, se não fez, seto a próxima. (Não sei se essa foi a melhor opção)

A dúvida é, estou querendo refatorar dado uma Cidade e um Serviço de Entrega, retornar o valor do frete. Segue:

public class Correios implements ServicoDeEntrega {

    public double para(Cidade cidade) {

        if (cidade instanceof RioDeJaneiro)
            return 10;
        else if (cidade instanceof SaoPaulo)
            return 15;
        else
            return 0;

    }

}


public class FedEX implements ServicoDeEntrega {

    @Override
    public double para(Cidade cidade) {

        if (cidade instanceof RioDeJaneiro)
            return 50;
        else if (cidade instanceof SaoPaulo)
            return 40;
        else
            return 0;
    }

}

Como fazer pra resolver esses IFs ? Qual melhor padão a utilizar?

Grato.

5 respostas

Oi Thiago,

Sua interface Cidade deveria ter um getValorEntrega(), e as classes que implementarem teriam seu valor específico. Assim você poderia fugir facil desses ifs

Olá Thiago, tudo bem? Uma alternativa simples pra remover esses ifs seria extrair o valor de frete para cada implementação de cidade. Bastaria adicionar um método getValorDeFrete (abstrato) na classe Cidade, implementá-lo em cada uma das filhas, e graças ao polimorfismo seu código ficaria assim:

public double para(Cidade cidade) {
    return cidade.getValorDeFrete();
}

Faz sentido? Outra possibilidade seria, no lugar de se acoplar o frete dessa forma com a classe Cidade, criar uma nova interface que tenha esse único método, fazer com que as classes que fazem sentido implementem essa interface e passá-la como argumento do método para. Um abraço

Sim. Pensei nessa possibilidade, porém ao implementar o getValorFrente(), eu estaria colocando os valores apenas por cidades.

Gostaria de retornar valores com a combinação de Tipo de frete (Ex: Correios, FedEX) com cidades.

Imaginem que para Rio de Janeiro retornasse 15,00 para Correios e 30,00 para o FedEX.

São Paulo, 10,00 para Correios e 20 para FedEX e assim por diante. De modo que seja fácil a implementação de uma nova Cidade e novo tipo de Entrega.

Grato.

solução!

Oi Thiago,

Generalize o problema. Se a quantidade de maneiras diferentes de calcular frete for pequena, mas o número de cidades grande, então eu faria algo como:

interface Frete {
  double porSedex();
  double porCorreios();
  double outroTipoAqui();
}

E aí, cada Cidade implementando essa interface.

A ideia é você fugir desses instanceofs que você fez. Veja que sempre que faz um if desse, toda vez que criar um novo tipo, você precisará voltar para esse trecho de código, e adicionar outro.

O que acha?

Sim. Essa ideia, fugir dos IFs.

Olha como ficou:

public class FedEX implements ServicoDeEntrega {

    @Override
    public double para(Frete frete) {

        return frete.porFedEX();
    }

}


public class RioDeJaneiro implements Cidade, Frete {

    private String nome;

    public RioDeJaneiro(String nome) {
        this.setNome(nome);
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Override
    public double porFedEX() {
        return 50;
    }

Perfeito!

Obrigado Maurício e obrigado galera :)