2
respostas

Criaçao dinamica de objetos

olá, sobre criação de objetos sempre caio em uma dúvida.

Por exemplo Esses dias eu tive que fazer um código que deveria fazer várias validações. Só que esse conjunto de validações variava de acordo com o cliente. Por exemplo, se fosse pro banco do brasil, eram as validações X Y Z; se fosse bradesco, seriam A B C...etc ou seja, cada banco tem a sua validação. Eu não queria simplesmente fazer uma classe pra cada um e aí fazer em outra classe um monte de if pra saber qual era o banco e então pegar uma instância do validador dele. Entao o que fiz foi: Criei uma interface IValidador e fiz as implementações de cada banco. Na classe que ia chamar a validação, usei reflection: coloquei num arquivo properties caminho(pacote) de cada validador, então eu pego o nome (ou código) do banco e por ele eu vou no properties, faço a reflection pro validador que quero e então ele segue a vida no "validador.validar", sendo que esse métood validar está na interface, então ficou algo transparente. A solução em si funciona, mas não me agradou muito. Eu fugi do problema de ter que ficar criando vários ifs, por outro lado não sei se é legal também ir pro properties e reflection, pois da a sensação que apenas troquei o problema de lugar... e outra coisa é que usando reflection, eu tenho que instanciar o objeto na mão, e aí eu perdi a injeção de dependência tanto desse objeto quanto dos outros que estão dentro do validador

então a questão que não entendo muito bem eh essa..qual a solução pra criaçao dinamica dos objetos? ok, tem os desing patterns e tudo mais, mas eles resolvem quando quem chama eles, ja sabe qual precisa no meu caso, por exemplo, se eu nao fosse fazer como fiz, eu teria que ter um monte de if na classe que chama os validadores, entao só teria trocado o problema de lugar, também..

2 respostas

Fala, Fernando.

Achei a sua solução bacana e extensível.

Enums

Uma maneira comum no mercado é usar enums. Um enum do Java pode ter construtores, atributos e métodos.

Então, você poderia fazer:

public enum TipoValidador {

  BANCO_DO_BRASIL(new BancoDoBrasilValidator()),
  BRADESCO(new BradescoValidator());

  private IValidator validator;

  private TipoValidador(IValidador validator) {
      this.validator = validator;
  }

  public IValidator getValidator() {
      return this.validator;
  }

}

Assim, uma classe, sei lá, Pagamento pode ter um atributo do tipo do enum TipoValidador que vem lá do BD.

Tipo:

public class Pagador {

    //...

    public void efetua(int idPagamento) {
        Pagamento p = dao.findById(idPagamento);
        IValidator v = p.getTipoValidador().getValidator();
        v.valida();
        //...
    }

}

Class.forName

Me lembrou o Class.forName("com.mysql.jdbc.Driver") que fazíamos antigamente, pra instanciar um Driver JDBC. Só que ao invés de deixar o nome da classe chumbado no código, você colocou o nome da classe em um .properties.

Service Provider Interface (SPI)

Hoje a gente nem precisa do Class.forName porque, no Java 6 se não me engano, foi criado o mecanismo de Services no Java.

Pra drivers, por exemplo, o DriverManager vasculha os JARs do ClassPath e olha quais tem o arquivo META-INF/services/java.sql.Driver (o nome do arquivo é com pontos mesmo). Nesse arquivo vai ter o nome da classe que precisa ser usada.

O SPI é útil pra uma arquitetura de plugins, em que você não conhece a implementação das suas interfaces e nem quer que o dev tenha que criar um main da vida pra grudar uma coisa com a outra... Basta ter um jar que tenha um arquivo com o nome da interface no META-INF/services/.

https://docs.oracle.com/javase/tutorial/ext/basics/spi.html#introduction

Caramba, vim aqui perguntar uma coisa e acabei com mais conhecimento sobre Enums! Gostei demais da resposta e já apliquei em um desenvolvimento de aprendizado que eu estava fazendo. Show de bola!!