Pattern para modelagem de coleção de constantes

Pessoal, boa tarde.

No projeto que estou alocado, existem alguns campos pré-codificados, cujo valores não estarão em uma tabela do banco de dados, mais sim no código do sistema. Podemos dizer que estes valores serão constantes dentro do meu sistema. Um exemplo é o campo tipo_documento_identidade, que possui os valores “Carteira de Identidade”, “Carteira Profissional” e “Passaporte”.

A minha dúvida é sobre a melhor forma de se trabalhar com estes valores, já que eles serão utilizados em várias partes do sistema. Um colega aqui do trabalho viu que daria para resolver isto com Ennumerations, só que nós estamos utilizando a versão 1.4.2-08 do java, e este recurso só está disponível para a versão 5 do java.

Qualquer luz sobre este assunto será bem vinda.

Um dia eu vi uma dica legal em um site. Não me lembro o link se não eu passaria para vc.
Mas era ± assim:


class TipoDocumentoIdentidade {
   private int tipo;
   private TipoDocumentoIdentidade (int tipo) {  this.tipo = tipo; }

   public static final TipoDocumentoIdentidade CARTEIRA_INDENTIDADE = new TipoDocumentoIdentidade(0);
   public static final TipoDocumentoIdentidade CARTEIRA_PROFISSIONAL = new TipoDocumentoIdentidade(1);
   public static final TipoDocumentoIdentidade PASSAPORTE = new TipoDocumentoIdentidade(2);

  public boolean equals(Object object) {
     if (object != this) return false;

     if (!(object instanceof TipoDocumentoIdentidade)) return false;

     TipoDocumentoIdentidade t (TipoDocumentoIdentidade) object;   
 
     if (this.tipo == t.tipo)
        return true;
     else
       return false;
  }
}

public void teste (TipoDocumentoIdentidade tipoDocumento) {
   if (tipoDocumento.equals(TipoDocumentoIdentidade.CARTEIRA_INDENTIDADE)) {
    // é identidade;
  }
}

teste(TipoDocumentoIdentidade.CARTEIRA_INDENTIDADE);

Isso evita vc colocar valores inválidos

jpprogrammer,

a sua solução parece ser muito boa. Baseado nela, eu criei uma interface chamada TipoConstanteInterface, uma classe abstrata chamada TipoConstanteAbstrata que implementa TipoConstanteInterface, e finalmente a classe que extende a classe abstrata e aonde está definido as constantes, chamada TipoDocumentoIdentidade.

Abaixo segue o código da interface e das classes que criei:

/* Interface TipoConstanteInterface. */
import java.util.List;

public interface TipoConstanteInterface {

    public String getCodigo();
    public String getDescricao();
    public List listar();
    public boolean equals(Object object);  
}
/*
 * Classe abstrata TipoConstanteAbstrata, que implementa a interface
 * TipoConstanteInterface.
 */
public abstract class TipoConstanteAbstrata implements TipoConstanteInterface {

    private String codigo;
    private String descricao;
    
    /**
     * 
     */
    public TipoConstanteAbstrata(String codigo, String descricao) {
        this.codigo    = codigo;
        this.descricao = descricao;
    }

    /* (non-Javadoc)
     * @see br.com.abnc.detnet.renach.dal.interfaces.TipoConstanteInterface#getCodigo()
     */
    public String getCodigo() {
        return codigo;
    }

    /* (non-Javadoc)
     * @see br.com.abnc.detnet.renach.dal.interfaces.TipoConstanteInterface#getDescricao()
     */
    public String getDescricao() {
        return descricao;
    }
    
    /* (non-Javadoc)
     * @see br.com.abnc.detnet.renach.dal.interfaces.TipoConstanteInterface#equals()
     */
    public boolean equals(Object object) {
        if ((object != this) || (!(object instanceof TipoConstanteAbstrata))) {
            return false;
        } else { 
            TipoConstanteAbstrata tipoConstante = (TipoConstanteAbstrata) object;
  
            if (this.codigo.equals(tipoConstante.codigo)) {
                return true;
            } else {
                return false;
            }
        }
    }
    
}
/*
 * Classe TipoDocumentoIdentidade que herda de 
 * TipoConstanteAbstrata.
 */
public class TipoDocumentoIdentidade extends TipoConstanteAbstrata {

    public static final TipoConstanteAbstrata CARTEIRA_INDENTIDADE  = 
        new TipoDocumentoIdentidade("0", "Carteira de Identidade");
    public static final TipoConstanteAbstrata CARTEIRA_PROFISSIONAL = 
        new TipoDocumentoIdentidade("1", "Carteira Profissional");
    public static final TipoConstanteAbstrata PASSAPORTE            = 
        new TipoDocumentoIdentidade("2", "Passaporte");
    public static final TipoConstanteAbstrata CARTEIRA_RESERVISTA   = 
        new TipoDocumentoIdentidade("3", "Carteira de Reservista");
    
    /**
     * @param codigo
     * @param descricao
     */
    public TipoDocumentoIdentidade(String codigo, String descricao) {
        super(codigo, descricao);
    }

    /* (non-Javadoc)
     * @see br.com.abnc.detnet.renach.dal.interfaces.TipoConstanteInterface#listar()
     */
    public List listar() {
        List listaDocumentos = new ArrayList();
        
        listaDocumentos.add(CARTEIRA_INDENTIDADE); 
        listaDocumentos.add(CARTEIRA_PROFISSIONAL); 
        listaDocumentos.add(PASSAPORTE); 
        listaDocumentos.add(CARTEIRA_RESERVISTA);
        
        return listaDocumentos;
    }

}

Fiz desta forma para ficar o mais genérico possível. Por exemplo, eu necessitarei carregar comboboxs em minhas páginas contendos o valor destas constantes. Da forma que defini, poderei criar uma custontag que realize este preenchimento, e que não necessitará conhecer o valor que deverá preencher, pois ela acessará na verdade a interface. Já a classe abstrata implementa os métodos comuns de todas as classes de constantes, como carregar o codigo e descricao no construtor, resgatar o codigo ou a descricao, e realizar a comparação de igualdade entre os objetos.

E então, você acha que desta forma está bem implementado, ou poderia ser melhorado?

Assim, estou definindo uma interface padrão que poderá ser utilizada, por exemplo, numa custon tag que deverá fazer o preenchimento de um determinado combobox, mais não sabe qual tipo de valor constante deverá capturar, e uma classe abstrata que

  • EDIT - Por favor, ponham os tags [ code ] -

Eu acho melhor vc ter só a classe e criar os métodos de listagem nela mesmo.
deixe o contrutor private, para só ter as opções necessárias.
Com contrutor public alguem pode criar um tipo novo e burlar o constraint.
ex:


public void teste(TipoDocumentIdentidade tipoDocumento) {

}

teste(new TipoDocumentIdentidade(666,"Tipo do Mal"));

O objetivo deste pattern é restringir a criação de tipos pelo usuário da classe.
Isso pode acarretar problemas graves…

No caso, se eu deixar o construtor da classe abstrata como publica, e da classe concreta como abstrata, acho que resolveria este problema, concorda?

Vc quis dizer private.
Resolve.
Mas esse negocio de interface e classe abstrata pode complicar um pouco.
Por que motivo vc quer isso ?

Realmente, confundi as bolas… Seria Private na classe abstrata, e public na classe concreta.

Gostaria de fazer desta forma, pois iria possuir vários tipos de coleções de constantes. Desta forma pretendia diminuir o trabalho na implementação e a duplicação de código.

Mais não precisarei mais utilizar este artifício. Um dos Analistas do projeto resolveu colocar estes dados em uma tabela do banco de dados. Viu que iria ser mais fácil de se trabalhar

De qualquer forma valeu pela ajuda amigo. :slight_smile: