Public static <classe> create() {} // [RESOLVIDO]

Alguém sabe me dizer quando é vantagem utilizar o construtor privado e um método estático para criar uma instância ao invés de usar o construtor normal chamado com new?

e ae kra… acho q vc tah falando de sngleton neh?

tipo… esse método estático retorna a instancia da classe (se ela jah foi criada) ow instancia e a retorna. Assim permite-se que se tenha no max um objeto dessa classe criado.

A vantagem é simples: Encapsulamento.
O que tlv não seja obvio é que o encapsulamento permite que a contrução do objeto em causa mude com o tempo.

Se hoje vc faz X x = new X(); e amanhã quer fazer sempre X x = new X(); x.setABC(abc), vc consegue mudar facilmente depois.

à primeira vista parece chato e desnecessário encapsular um new , mas esse é o primeiro passo se vc quer vir a usar injeção de dependência ( por exemplo), devolução de objetos que estendam a classe pai , proxys , ou simplesmente se quer deixar seu codigo aberto para fazer alguma coisa diferente de new no futuro.

Tem uma outra vantagem menos obvia que é a da escrita. É mais simples usar um método estático
que devolve um objeto da classe necessária. Isto é tanto mais util quanto mais fluente for a interface da classe em causa.

Resumindo, é bom e recomenda-se.

P.S: Ah! e usar um método estático para encapsular o new não tem nada a ver com Singleton.
Encapsular o new deste jeito é um padrão chamado Factory Method o qual o Singleton tb usa. Só isso.

Blz! Brigadão! :slight_smile:

Ficou meio difícil entender o que o Sérgio quis dizer, mas do que foi possível apreender do texto dele eu não vejo no que um static factory é “mais encapsulado” do que um construtor. Se vc precisa inicializar algum membro da classe com um valor passado na construção, você simplesmente cria outro construtor, uai!
Static Factories são úteis em situações como quando eu não quero criar sempre uma nova instância, e quero poder usar um cache (do que o singleton é uma das variações mais conhecidas), ou quando eu quero ter a oportunidade de criar uma instância cujo tipo é um subtipo do que é retornado pelo static factory, algo que não é possível com um construtor comum.
Um static factory permite que vc controle com mais precisão o que é retornado, e às vezes é interessante ter essa flexibilidade, mas não todo o tempo.
É bom, mas use apenas quando necessário, mesmo porque muitos frameworks dependem da classe ter um construtor padrão disponível, e porque não faz sentido vc se distanciar da semantica normal de construção quando vc não tem necessidade de qualquer uma das coisas que um static factory lhe provê.

Algumas classes deixam o construtor aberto E possuem factories, como as classes wrappers (por exemplo Integer(int) e Integer.valueOf(int)). Entao da pra usar as duas estrategias se voce quiser.

[quote=eliziario]Ficou meio difícil entender o que o Sérgio quis dizer, mas do que foi possível apreender do texto dele eu não vejo no que um static factory é “mais encapsulado” do que um construtor.
[/quote]

O codigo


XDate hoje = new XDate(); // A

XDate hoje = XDate.today(); // B

O exemplo é meio batido , mas …

Imagine-se que temos um monte de codigo espalhado por várias classes onde é usada a sintaxe A
Imagine-se que queremos agora fornece um método que retorne um filho de XDate que depende de alguma outra coisa. Com o método A não tem como fazer isso a não ser usando refractoring the search and replace.
Com o método B fazer essa alteração é trivial bastando mudar apenas o codigo dentro do método today().

Porquê é mais encapsulado ? Bom, porque ao chamar today() vc não sabe como a data é inicializada. Vc pode supor que é um new sendo dado, mas pode muito bem ser um class.newInstance() onde class é dinamcamente carregada de um arquivo de configuração. Vc simplesmente não sabe. É um caisa negra. E por isso é mais encapsulado.

Este tipo de construção é util em objetos de valor como datas e números. Vc pode até incluir cache como bem falou para os numeros mais usados como 1 e 0 (O Integer e o BigDecimal tem este tipo de cache , se não me falha a memória).

Outra vantagem é que ao chamar um método ele tem um nome, e portanto é explicito que tipo de objeto estou construindo. today() é mais explicito que new XDate(), que pode significa hoje, mas tb pode significa “data vazia”.

Por outro lado, o fato de criar este métodos especiais não significa que a classe não possa ser inicializada como um bean, apenas significa que quando não estamos em reflection, ou seja, quando é um ser humano escrevendo , é muito mais natural usar os métodos com nomes explicitos.

Finalmente, ao ser usado especialmente em objetos de valor permite um certo grau de fluidez na escrita. Dependendo do objeto, pode ser mais ou menos util, mas é concerteza mais limpo


XDate amanha = (new XDate()).next();

XDate amanha = XDate.today().next();

O fato de ter um método pode ser ainda vantajoso para diminuir o trabalho braçal


Money 10reais = new Money(10 , Currency.getInstance("BRL"));

Money 10reais = Money.money(10 , "BRL");

Money 10reais = Money.reais(10); 

Sergio,

XDate hoje = new XDate(); // A   

XDate hoje = XDate.today(); // B  

Uai, depois dessa suposta mudança vai existir a necessidade de manter a o método antigo?
Se não, o seguinte, supostamente funcionaria:

XDate hoje = new XDate(); // A   
XDate hoje = XDate.today(); // B (alguma macumba aqui dentro)
XDate hoje = new XDate(); // C (a macumba feita em B é feita aqui, perdemos esse construtor  

Ou não?
B continua sendo mais flexivel, ex: nem um construtor ele é …
De resto, em relação a semântica, concordo com você. Só não sei se vale a pena fazer isso com frequência e em qualquer classe, mais exemplos, por favor.

[quote=faq]
Se não, o seguinte, supostamente funcionaria:

XDate hoje = new XDate(); // A   
XDate hoje = XDate.today(); // B (alguma macumba aqui dentro)
XDate hoje = new XDate(); // C (a macumba feita em B é feita aqui, perdemos esse construtor  

Ou não?
B continua sendo mais flexivel, ex: nem um construtor ele é …
De resto, em relação a semântica, concordo com você. Só não sei se vale a pena fazer isso com frequência e em qualquer classe, mais exemplos, por favor.[/quote]

O construtor nem sempre funciona. A primeira instrução do construtor é sempre super() e às vezes isso é um empecilho porque vc quer fazer algum código antes de super(). Ai a solução é o método estático.

Como disse antes este tipo de construção é especialmente indicado para objetos de valor. Isto porque com valores normalmente estamos interessados em operar sobre eles mais do que criá-los. Estamos tb interessados normalmente em valores especiais que são obtidos com estes métodos de construção especiais.

Uma outra vantagem que faltou mencionar é que com estes métodos só precisamos de um construtor, o default. Já que o método tem acesso aos atributos da classes eles podem ser setados diretamente se necessário.

Quanto a usar no caso geral usar um construtor estático não é mal nenhum, como disse é até um padrão de projeto.
Não vejo qual seja a desvantagem.

Em casos gerais em que o objeto não é de valor será dificil precisar de um método deste tipo, mas é possivel:

Account a ...
Account b ...

AccountTransfer transfer = AccountTransfer.transferFrom(a).to(b).amount(Money.reais(30.40));

// em oposição a 

Money m = new Money (30.40, "BRL");

AccountTransfer transfer = new AccountTransfer();
transfer.setFrom(a);
transfer.setTo(b);
transfer.setAmount(m);