Tempo de leitura: menos de 1 minuto

E aí pessoal, como vão as boas práticas de desenvolvimento?
Quando comecei a programar Java, um professor me disse que um objeto bem construído deveria ter todos atributos obrigatórios inicializados pelo construtor da classe.
Então vejamos, imagine que tenhamos a seguinte classe:
[code language=”java”]
public class Pessoa {
private String cpf;
private Integer idade;
private String nome;
private String orgaoEmissor;
private String rg;
private String tituloEleitor;
}
[/code]
Se seguirmos a orientação do meu professor, teríamos que ter um construtor na classe que inicializasse todos os atributos de uma única vez. Seria algo assim:
[code language=”java”]
public Pessoa(final String pNome,
final Integer pIdade,
final String pRg,
final String pOrgaoEmissor,
final String pCpf,
final String pTituloEleitor) {
nome = pNome;
idade = pIdade;
rg = pRg;
orgaoEmissor = pOrgaoEmissor;
cpf = pCpf;
tituloEleitor = pTituloEleitor;
}
[/code]
Agora, imagina você precisando instanciar essa classe, são 6 parâmetros que você vai precisar passar na inicialização, além disso, você precisará saber a ordem certas dos parâmetros, já que 5 parâmetros são do tipo String. Caso você confunda e passe o CPF no lugar do RG, isso vai fazer com que seu objeto gere resultados incoerentes.
Uma forma de minimizar esse problema é usar um design pattern chamado Builder. Esse pattern tem por objetivo, auxilar na construção de um objeto com muitos parâmetros, como nosso exemplo.
Vejamos como ficaria a classe do nosso exemplo usando esse pattern:
[code language=”java”]
public class Pessoa{
private String nome;
private Integer idade;
private String rg;
private String orgaoEmissor;
private String cpf;
private String tituloEleitor;
public Pessoa(final PessoaBuilder pBuilder) {
nome = pBuilder.nome;
idade = pBuilder.idade;
rg = pBuilder.rg;
orgaoEmissor = pBuilder.orgaoEmissor;
cpf = pBuilder.cpf;
tituloEleitor = pBuilder.tituloEleitor;
}
public static class PessoaBuilder {
private String nome;
private Integer idade;
private String rg;
private String orgaoEmissor;
private String cpf;
private String tituloEleitor;
public PessoaBuilder(final String pNome) {
nome = pNome;
}
public PessoaBuilder idade(final Integer pIdade) {
idade = pIdade;
return this;
}
public PessoaBuilder rg(final String pRg) {
rg = pRg;
return this;
}
public PessoaBuilder orgaoEmissor(
final String pOrgaoEmissor) {
orgaoEmissor = pOrgaoEmissor;
return this;
}
public PessoaBuilder cpf(final String pCpf) {
cpf = pCpf;
return this;
}
public PessoaBuilder tituloEleitor(
final String pTituloEleitor) {
tituloEleitor = pTituloEleitor;
return this;
}
public Pessoa build() {
return new Pessoa(this);
}
}
}
[/code]
O exemplo é extenso, né? Mas não é nenhum bicho de sete cabeças.
Não existe maneira certa de criar um builder, nesse exemplo, o builder foi criado como uma inner class em Pessoal, mas nada impede a separação em classes distintas.
Cada método exerce a função de um setter, acumulando os valores no builder. Quando o método build é chamado, aí sim o objeto Pessoa é criado.
Vejamos se agora ficou mais fácil instanciar Pessoa:
[code language=”java”]
public Pessoa getPessoa() {
return Pessoa.criarPessoa("Eder")
.idade(32)
.cpf("012.345.678-90")
.rg("12.345.456-9")
.orgaoEmissor("SSP/SP")
.tituloEleitor("1234567890")
.build();
}
[/code]
O que fizemos aqui, foi complicar um pouquinho a classe, escrevendo mais código, mas facilitamos imensamente o uso.
Vantagens:
- Não precisamos mais saber a ordem dos campos na inicialização;
- Não há necessidade de preencher todos os campos, de qualquer forma, conseguimos garantir que o objeto estará sempre em estado válido;
- A forma de uso fica muito mais intuitiva.
Outros exemplos:
[code language=”java”]
Response.created(createdUri).build();
Response.ok(f, mt).build();
Response.status(Responses.NOT_FOUND).entity(message)
.type("text/plain").build();
[/code]
Até mais pessoal!
Link permanente