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

Dúvida: Ex.5 - Chain Of Responsability - Recebendo o próximo item da corrente pelo construtor

A parte de receber pelo construtor eu entendi. Pois dessa forma você força o desenvolvedor a não esquecer de determinar o próximo elemento a ser verificado pela corrente, onde usando o método "setProximo" ele pode acabar esquecendo de determinar.

O problema é que uma vez que determina-se o próximo item pelo construtor, como fica no método "main"? E na classe que especifica a sequencia da corrente? Visto que um dos métodos que recebe o próximo elemento pelo construtor será o primeiro da corrente, e o primeiro da corrente não irá ter elemento pra receber no construtor, já que ele é o que está começando a corrente.

Estou tendo problemas de NullPointer Exception já que vem nulo.

Como fica? Não estou conseguindo resolver!

5 respostas

Daniel, posta seu código para dar uma olhada.

Segue o fonte das classes. Vou mandar todos, desculpe se não tinha necessidade, mas preferi postar todos pra garantir que todas as informações necessárias estivessem aí.

Classe CONTA:

public class Conta {

    private String nome;
    private double saldo;

    public Conta( String nome, double saldo ) {

        this.nome = nome;
        this.saldo = saldo;

    }

    /**
     * @return the nome
     */
    public String getNome() {
        return nome;
    }

    /**
     * @return the saldo
     */
    public double getSaldo() {
        return saldo;
    }

}

Classe "FormatadorDeRequisicao", que é a classe onde contém a determinação da sequencia da corrente, e é onde gera o problema já que ao instanciar o objeto "formatoXML" não tem o que colocar no construtor, entrando "nulo". Da forma que está aqui nem compilar compilaria visto que dá erro por não ter nada no construtor:

public class FormatadorDeRequisicao {

    public String formatar( Formato formato, Conta conta ) {

        FormatoXML formatoXML = new FormatoXML();
        FormatoCSV formatoCSV = new FormatoCSV( formatoXML );
        FormatoPORCENTO formatoPorCentro = new FormatoPORCENTO( formatoCSV );

        return formatoXML.getRetorno( formato, conta );
    }

}

Enum contendo os valores para direcionar o tipo de retorno do aplicativo "Formato":

public enum Formato implements FormatoRequisicao {

    XML,
    CSV,
    PORCENTO;

    @Override
    public String getRetorno(Formato formato, Conta conta) {
        return "";
    }

}

Método que retorna o valor CSV "FormatoCSV": ``` public class FormatoCSV implements FormatoRequisicao {

private FormatoRequisicao requisicao;

public FormatoCSV( FormatoRequisicao requisicao ) { this.requisicao = requisicao; }

@Override public String getRetorno(Formato formato, Conta conta) { if( formato == Formato.CSV ) { return conta.getNome() + ";" + conta.getSaldo(); } else { return this.requisicao.getRetorno( formato, conta ); } }

}

Desconsidere a classe "FormatoCSV" anterior, sem querer postei sem estar pronto, considere daqui pra baixo a continuação das postagens das classes:

Classe "FormatoCSV":

public class FormatoCSV implements FormatoRequisicao {

    private FormatoRequisicao requisicao;

    public FormatoCSV( FormatoRequisicao requisicao ) {
        this.requisicao = requisicao;
    }

    @Override
    public String getRetorno(Formato formato, Conta conta) {
        if( formato == Formato.CSV ) {
            return conta.getNome() + ";" + conta.getSaldo();
        } else {
            return this.requisicao.getRetorno( formato, conta );
        }
    }

}

Formato que retorna os valores da conta entre "%" classe "FormatoPORCENTO":

public class FormatoPORCENTO implements FormatoRequisicao {

    private FormatoRequisicao requisicao;

    public FormatoPORCENTO( FormatoRequisicao requisicao ) {
        this.requisicao = requisicao;
    }

    @Override
    public String getRetorno(Formato formato, Conta conta) {
        return conta.getNome() + "%" + conta.getSaldo();
    }

}

Classe que retorna o valor "XML", classe "FormatoXML":

public class FormatoXML implements FormatoRequisicao {

    private FormatoRequisicao requisicao;

    public FormatoXML( FormatoRequisicao requisicao ) {
        this.requisicao = requisicao;
    }

    @Override
    public String getRetorno( Formato formato, Conta conta ) {
        if( formato == Formato.XML ) {
            return "XML";
        } else {
            return this.requisicao.getRetorno( formato, conta );
        }
    }

}

Interface "FormatoRequisicao":

public interface FormatoRequisicao {

    String getRetorno( Formato formato, Conta conta );

}

Classe contendo o método MAIN:

public class Main {

    public static void main(String[] args) {

        Conta conta = new Conta( "Daniel", 2890.45d );

        FormatadorDeRequisicao formatador = new FormatadorDeRequisicao();

        System.out.println( formatador.formatar(Formato.XML, conta) );
        System.out.println( formatador.formatar(Formato.CSV, conta) );
        System.out.println( formatador.formatar(Formato.PORCENTO, conta) );

    }

}
solução!

Para contornar o problema de null pointer, se é que eu entendi direito a sua dúvida, basta inverter a ordem em que os objetos são instanciados.

Algo tipo assim:

public class CalculadorDeProcessadorRequisicao {
    public String processarRequisicao(Requisicao requisicao, ContaBancaria conta) {
        // Tive que inverter a ordem de instaciação dos objs

        ProcessadorRequisicao pVazio = new ProcessadorRequisicaoVazio();
        ProcessadorRequisicao pPORCENTO = new ProcessadorRequisicaoPORCENTO(pVazio);
        ProcessadorRequisicao pCSV = new ProcessadorRequisicaoCSV(pPORCENTO);
        ProcessadorRequisicao pXML = new ProcessadorRequisicaoXML(pCSV);

        return pXML.processar(requisicao, conta);
    }
}

Fica um pouco confuso para quem vai dar manutenção, pois a ordem natural de formação da cadeia está ao contrário.

Show de bola Gustavo. Fui meio lerdo agora, esqueci do objeto da classe vazia que não retorna nada. Resolveu! Obrigadão!