Classe com somente uma instancia

Olá pessoal, tudo bem? Gostaria de saber se há alguma forma de fazer uma classe em que possa ocorrer somente uma instância dessa e que se alguem de fora da classe fosse usá-la, teria que obrigatoriamente usar essa instancia?

Apareceu essa pergunta no livro use a cabeça Java. Tentei de tudo mas não consegui fazer isso, alguém sabe como faz??

Muito obrigado!

Esse é o famoso “pattern” ou “antipattern” Singleton.

public class Singleton {

    private static Singleton myInstance;
 
    // com o construtor private não é possível instanciar a classe com o operador new de fora da classe
    private Singleton() {
    }

    public static Singleton getInstance() {
       if( myInstance == null ) {
          myInstance = new Singleton();
       }
       return myInstance;
    }

}

Um singleton?

[code]
public class Singleton {
private static Singleton instancia = new Singleton();

private Singleton() {
}

public static Singleton getInstance() {
	return singleton;
}

}[/code]

Ahh, e para usar faça assim:

public class Test {

   public static void main( String[] args ) {
      
      Singleton sing = Singleton.getInstance();
      
   }

}

Evite o uso excessivo de Singletons, pois hoje é considerado um anti-pattern…Prefira sempre injeção de dependências e inversão de controle (IoC), usando, por exemplo o Spring Framework :wink:

Hum, entendi, então o segredo é criar uma instancia dentro de um método static da classe e deixar o construtor como private?

Muito obrigado ae! Valews!!

:lol:

A primeira coisa é vc compreender o pattern Factory.

Para vc ter apenas uma instancia vc não pode usar new, pois isso cria uma nova instância e não ha nada que possamos fazer para evitar. Como instanciar então? Vais ter que ter uma fabrica de objetos, que tem a mesma função pratica do new, porém com outra sintaxe e significado. Vc pedira a fabrica: me de uma instancia dessa classe, e ela retornará o que vc pede. Por isso vc tem métodos getInstance que são estáticos para esse tipo de construção: a sua fabrica ira distribuir referencias de uma unica instancia e uma das formas de vc obter isso é armazenando a instancia que vc quer distribuir como atributo estático. De quebra vc cria um contrutor privado para que ninguem viole a sua classe :wink:

Cuidado ao tentar usar singletons em programas multithread, a implementação do Diego, por exemplo, não é sincronizada a ponto de evitar que ele instancie mais de uma vez.

Nesses casos ou implemente o método com synchronized, ou use aquele que postei.

Não entremos em detalhes se o Singleton é ou não um anti-pattern, ou se ele deve ou não ser utilizado.
O importante é entender quais são os problemas dessa solução e quais são suas vantagens. Programar é basicamente tomar decisões baseadas num contexto ou, num jargão mais administrativo, analisar trade-offs.

O singleton, em especial no Java, tem sérios problemas:

  1. Não é possível garanti-lo entre vários class-loaders;
  2. A solução com lazy initialization (no caso, a primeira postada, onde a variável estática começa com null) não é thread-safe. Poderia ser tornada colocando synchronized no método getInstance(). Esse erro é extremamente comum.
  3. É uma classe difícil de se testar, de se substituir por mocks, etc.
  4. Uma vez instanciado, ele não pode ser apagado (dá para fazer com WeakReferences, mas isso gera um código relativamente complexo);

Por outro lado:

  1. É rápido de escrever;
  2. É simples, há pouco overhead de classes, tempo e memória;
  3. Não tem dependências externas (você não precisa anexar um framework de IoC para usa-lo).
  4. Não depende de reflexão.

Portanto, se você estiver fazendo um software pequeno e embarcado, como no caso de uma aplicação J2ME, o Singleton é uma boa alternativa de design. Software single-threaded, com um único class loader, também se beneficia desse padrão (como é o caso de vários jogos, por exemplo).

Agora, ele se torna inadequado para praticamente todos os softwares comerciais hoje em dia, especialmente os web. Há muita discussão sobre esse padrão ser bom ou não, algumas delas aqui no GUJ (eu e o pcalcado já discutimos aqui sobre isso tb).

O Bruno está certo… o meu exemplo não serve para aplicações multi-thread… nesse caso existem várias opções como utilização de blocos de inicialização, métodos synchronized ou como no exemplo dado, declarar e inicializar em uma mesma linha.

Dessa forma que citaram ai, ela pode ser clonada, ou estou enganado?
Como eu poderia bloquear o clone dela?

[quote=thiagofesta]Dessa forma que citaram ai, ela pode ser clonada, ou estou enganado?
Como eu poderia bloquear o clone dela?[/quote]

Faça a classe implementar o Cloneable, e dentro do método clone atire um CloneNotSupportedException

Bruno Laturner
Obrigado

Ai sim, implementado tudo o que foi dito, ai sim seria um verdadeiro singleton

ola pessoal,

uma outra solucao interessante pra se fazer um singleton é usar um enum:


public enum MySingleton {
	INSTANCE;
       /* atributos e metodos */
}

ai pra usar:

MySingleton singleton = MySingleton.INSTANCE;

[]s

Mas IoC não depende de um framework pra utilizar, e nunca vi um padrão que precisasse de reflexão.

Nunca tinha pensado em Singleton com enum, achei a idéia foda =o

O que os experts tem a dizer sobre isso? Singleton com enum? ViniGodoys da vida emitam um parecer!

Em momento nenhum eu falei que IoC depende de um framework ou reflexão, embora o próprio artigo do fowler esteja recheado dela. IoC é um conceito mais abstrato.

Mas sua implementação comum é através de frameworks, como o Spring, que garantem thread-safety e configuração externa e que geralmente dependem de reflexão. E esses frameworks já são comumente encontrados em aplicações de grande porte o que torna ainda mais interessante a abolição do singleton nesses cenários.

Do contrário, você nunca vai ver um “Singleton Framework”, ou qualquer coisa parecida. O padrão é absurdamente simples. Mas sua limitação infelizmente o restringe a ambientes controlados, como os que citei a alguns posts atrás…

Isso é exatamente igual a fazer:

private static final MySingleton
{
    public MySingleton INSTANCE = new MySingleton() {}
}

E claro, adicionar os métodos valueOf, ordinal e demais métodos do enum (que perdem o sentido nesse caso). Mas veja a implementação do “Typesafe enum pattern”, no livro “Effective Java 1a edição” (não sei se está na segunda) e você vai entender certinho o que o enum faz por debaixo dos panos. :wink:

Então suas vantagens 3 e 4 não são válidas, pois nem para os caras comparados você precisa do que foi mencionado.
E usando seu exemplo do Spring, na verdade ele é um contra-exemplo, pois por padrão os seus beans são Singletons, e nesse caso, você usou o tal framework.


Muita gente complica o conceito de IoC. IoC é só mais um nome bonito, no fundo é um setter na sua classe, ou um argumento de um construtor.

Obs.: É óbvio que todo mundo prefere a abordagem por construtor.

[quote=rmarin]Então suas vantagens 3 e 4 não são válidas, pois nem para os caras comparados você precisa do que foi mencionado.
E usando seu exemplo do Spring, na verdade ele é um contra-exemplo, pois por padrão os seus beans são Singletons, e nesse caso, você usou o tal framework.[/quote]

Apesar de eu ter citado o exemplo de um framework de IoC, o Singleton continua não precisando de dependências externas, o que continua sendo uma vantagem.
E, ele também não depende de reflexão. Nem é comum utiliza-la. Então, porque essas vantagens não são válidas? As duas ainda se aplicam. Acho que o fato de também se aplicarem para o IoC, pelo menos em seu caso mais simples, não invalida elas para o Singleton, como sua frase deu a entender.

Eu não estava comparando o Singleton ao IoC, coisa que você fez desde o primeiro post que eu fiz. Eu apresentei algumas vantagens e desvantagens que considero na hora de escolher um Singleton. No C++, você acaba tendo menos poder com IoC - justamente pela ausência da reflexão, e por não poder usar as ótimas técnicas de dependency injection com a mesma facilidade - e parte dos problemas encontrados no Java não se aplicam: não existem multiplos class loaders e, dependendo do tipo de aplicação, nem muitas threads.

E também não disse que IoC é complicado, nem que era obrigatório ter um framework de IoC para faze-lo. Na verdade, releia os meus posts e veja que em momento nenhum condenei o IoC, muito pelo contrário, digo que ele é util na maioria dos casos.

Mas também vejo muita gente aqui no GUJ simplesmente repetindo a cartilha, sem parar para analisar se o padrão aplica-se ou não para seu caso, ou simplesmente trocando por frameworks sem sequer parar para analisar o impacto que o uso de um software terceiro trará a seu projeto. Como eu falei desde o primeiro post, o importante não é condenar ou não o Singleton. Mas entender o seu funcionamento, seus problemas e ser capaz de analisar se, em dada situação, ele é adequado ou não, se existem alternativas melhores, etc.

E isso vai variar de acordo com o conhecimento da equipe, a linguagem utilizada, o problema a ser resolvido e uma série de outros fatores, que não poderão ser cobertos em nossos posts por aqui.

Você sabe, tão bem quanto eu, que isso não é IoC. Só o setter ainda não inverteu o controle de nada. Até porque, uma das implementações clássicas de IoC está no mecanismo de eventos, fazendo a inversão do controle numa interface gráfica, por exemplo. E nesse caso, não há nem construtores e nem setters.

Na verdade, frameworks usam IoC o tempo todo. Como o próprio nome diz, inversion of control, está na inversão no controle. Ou seja, está no fato de normalmente uma implementação A controlar B, e você modificar a solução para que B controle A. Callbacks também são uma forma de IoC. MVC é uma forma de se implementar IoC (ao invés de eu pegar os dados e desenhar um Table, eu deixo que o Table se desenhe e pergunte ao model a respeito dos dados). No C++, existe IoC implementado de outras formas, como através do uso de policies e multimétodos. O setter e o construtor a mais na classe é um mecanismo, para viabilizar o IoC no caso da dependency injection, não o IoC em si.

Também é bom lembrar que um setter sem sincronização terá os mesmos problemas de thread-safety que um Singleton sem sincronização. Se você precisar da garantia que o Singleton fornece (e se propõe a resolver), ou seja, se estiver controlando um recurso único, também terá a necessidade de preocupações de multiplos class loaders. E daí surgem os frameworks de IoC, que tentam cobrir esses fatores, além de fornecer outros serviços.

É fácil comparar os problemas do Singleton levando em consideração todos esses aspectos, e depois dizer que o IoC também é simples, mas daí desconsiderando thread-safety e a necessidade inicial: ter uma única instância, mesmo entre vários classloaders.

Não estou dizendo com isso que o Singleton é melhor que IoC. O chato de postar coisas como essa é que tenho que ficar me repetindo e dizendo que realmente há soluções melhores na maior parte dos casos.

De fato, existem três problemas que irritam profundamente ao se usar Singleton:

  1. Ele agrega uma responsabilidade a mais na classe: a de gerenciar sua construção. Essa baixa de coesão pode ser prejucial ao deixar a classe mais complexa;
  2. É menos flexível. O mecanismo de construção da classe fica enraizado num método estático. E métodos estáticos não podem ser sobrescritos, herdados, ou não há possíbilidades de substitui-los sem recompilação de todo o código que usa a classe.
  3. Ele é normalmente usado como substituto de uma variável global: E fazer isso é tentador e realmente é a forma errada de utiliza-lo. Por isso, antes de optar por um Singleton deve-se realmente ter certeza de que a necessidade de uma única instância realmente existe.

Não são válidas porque nenhum outro pattern precisa disso! Nem mesmo IoC. Seria o mesmo que dizer que Singletons são bons porque não precisa comer piza de calabresa, mas é claro, nenhum outro também precisa.

E reafirmo, IoC é um setter ou um argumento no construtor de sua classe. E um simples setter já inverteu o controle.

Inverter o Controle é: Não buscar as coisas sozinho, é receber de alguém. E como fazer isso? Injeção de dependências. E como fazer a Injeção de Dependências? Qual a forma mais simples? Um setter. ou um argumento no construtor.

Eu prefiro via construtor por motivos óbvios.

Cara, relaxa, não precisa dar um milhão de exemplos, C++, livros do Franz Kafka. Observe o problema, e use suas palavras, acho mais convincente, mais franco. :wink: