Cite as considerações de design ao decidir entre o uso de um singleton e uma classe estática. Ao fazer isso, você é meio que forçado a contrastar os dois, então quaisquer contrastes que você possa encontrar também são úteis para mostrar seu processo de pensamento! Além disso, todo entrevistador gosta de ver exemplos ilustrativos. :)
design-patterns
cdleary
fonte
fonte
Respostas:
fonte
Que tal "evitar os dois"? Singletons e classes estáticas:
Em vez disso, examine as bibliotecas de injeção de dependência e inversão de contêiner de controle . Várias das bibliotecas IoC cuidarão do gerenciamento vitalício para você.
(Como sempre, há exceções, como classes de matemática estáticas e métodos de extensão C #.)
fonte
Hide Dependencies
algumas informações adicionais sobre este ponto: Você pode implementar o padrão Inversão de Controle, por exemplo, usando Ninject . Isso permite que você use apenas uma instância de um tipo vinculando-o a aSingletonScope
, o que significa que ele vai injetar a mesma instância, mas a classe não será única.Eu diria que a única diferença é a sintaxe: MySingleton.Current.Whatever () vs MySingleton.Whatever (). O estado, como David mencionou, é basicamente "estático" em ambos os casos.
EDIT: A brigada de enterro veio de digg ... de qualquer forma, pensei em um caso que exigiria um singleton. As classes estáticas não podem herdar de uma classe base nem implementar uma interface (pelo menos em .Net elas não podem). Portanto, se você precisar dessa funcionalidade, deverá usar um singleton.
fonte
Uma das minhas discussões favoritas sobre esse assunto está aqui (site original fora do ar, agora vinculado ao Internet Archive Wayback Machine .)
Para resumir as vantagens de flexibilidade de um Singleton:
fonte
Uma classe estática com um monte de variáveis estáticas é meio que um hack.
Um singleton com uma instância real é melhor.
O estado é APENAS na instância.
Portanto, o singleton pode ser modificado posteriormente para fazer pooling, instâncias locais de thread, etc. E nenhum código já escrito precisa ser alterado para obter o benefício.
É possível fazer algo semelhante com uma classe estática, mas haverá sobrecarga por chamada no despacho indireto.
Você pode obter a instância e passá-la para uma função como um argumento. Isso permite que o código seja direcionado para o singleton "certo". Sabemos que você só precisará de um deles ... até não precisar.
O grande benefício é que singletons com estado podem se tornar thread-safe, enquanto uma classe estática não pode, a menos que você a modifique para ser um singleton secreto.
fonte
Pense em um singleton como um serviço. É um objeto que fornece um conjunto específico de funcionalidades. Por exemplo
A fábrica de objetos é um objeto que executa um serviço específico.
Em contraste, uma classe cheia de métodos estáticos é uma coleção de ações que você pode querer realizar, organizadas em um grupo relacionado (A classe). Por exemplo
O exemplo StringUtils aqui é uma coleção de funcionalidades que podem ser aplicadas em qualquer lugar. O objeto de fábrica singleton é um tipo específico de objeto com uma responsabilidade clara que pode ser criado e repassado onde necessário.
fonte
As classes estáticas são instanciadas em tempo de execução. Isso pode ser demorado. Singletons podem ser instanciados apenas quando necessário.
fonte
Singletons não devem ser usados da mesma maneira que classes estáticas. Em essência,
é essencialmente o mesmo que
O que você realmente deveria fazer é tratar o singleton como apenas mais um objeto . Se um serviço exigir uma instância do tipo singleton, passe essa instância no construtor:
O serviço não deve estar ciente de que o objeto é um singleton e deve tratar o objeto apenas como um objeto.
O objeto pode certamente ser implementado, como um detalhe de implementação e como um aspecto da configuração geral, como um singleton se isso tornar as coisas mais fáceis. Mas as coisas que usam o objeto não deveriam saber se o objeto é um singleton ou não.
fonte
Se por "classe estática" você quer dizer uma classe que possui apenas variáveis estáticas, então elas realmente podem manter o estado. Meu entendimento é que a única diferença seria como você acessa essa coisa. Por exemplo:
versus
As partes internas do MySingleton obviamente serão diferentes entre eles, mas, questões de thread-safety à parte, ambos terão o mesmo desempenho em relação ao código do cliente.
fonte
O padrão Singleton é geralmente usado para servir dados independentes ou estáticos da instância, onde vários threads podem acessar dados ao mesmo tempo. Um exemplo pode ser códigos de estado.
fonte
Singletons nunca devem ser usados (a menos que você considere uma classe sem estado mutável um singleton). "classes estáticas" não devem ter nenhum estado mutável, exceto talvez caches thread-safe e similares.
Praticamente qualquer exemplo de um singleton mostra como não fazer isso.
fonte
Se um singleton é algo que você pode descartar, para limpar depois, você pode considerá-lo quando for um recurso limitado (ou seja, apenas 1 dele) que você não precisa o tempo todo e tem algum tipo de memória ou custo do recurso quando alocado.
O código de limpeza parece mais natural quando você tem um singleton, ao contrário de uma classe estática contendo campos de estado estático.
O código, no entanto, terá a mesma aparência de qualquer maneira, então se você tiver razões mais específicas para perguntar, talvez você deva elaborar.
fonte
Os dois podem ser bastante semelhantes, mas lembre-se que o verdadeiro Singleton deve -se ser instanciado (concedido, uma vez) e, em seguida, servido. Uma classe de banco de dados PHP que retorna uma instância de
mysqli
não é realmente um Singleton (como algumas pessoas a chamam), porque está retornando uma instância de outra classe, não uma instância da classe que tem a instância como um membro estático.Portanto, se você estiver escrevendo uma nova classe da qual planeja permitir apenas uma instância em seu código, pode também escrevê-la como um Singleton. Pense nisso como escrever uma classe normal e adicionar a ela para facilitar o requisito de instanciação única. Se estiver usando a classe de outra pessoa que não pode ser modificada (como
mysqli
), você deve usar uma classe estática (mesmo se não conseguir prefixar sua definição com a palavra-chave).fonte
Singletons são mais flexíveis, o que pode ser útil nos casos em que você deseja que o método Instance retorne diferentes subclasses concretas do tipo do Singleton com base em algum contexto.
fonte
Classes estáticas não podem ser transmitidas como argumentos; instâncias de um singleton podem ser. Conforme mencionado em outras respostas, observe os problemas de encadeamento com classes estáticas.
rp
fonte
Um singleton pode ter um construtor e um destruidor. Dependendo do seu idioma, o construtor pode ser chamado automaticamente na primeira vez que seu singleton é usado, ou nunca se seu singleton não for usado. Uma classe estática não teria essa inicialização automática.
Assim que uma referência a um objeto singleton é obtida, ela pode ser usada como qualquer outro objeto. O código do cliente pode nem mesmo precisar saber se está usando um singleton se uma referência ao singleton for armazenada anteriormente:
Isso obviamente torna as coisas mais fáceis quando você opta por abandonar o padrão Singleton em favor de um padrão real, como IoC.
fonte
Use o padrão singleton quando precisar computar algo em tempo de execução que você calcularia em tempo de compilação se pudesse, como tabelas de pesquisa.
fonte
Acho que um lugar onde Singleton fará mais sentido do que a classe estática é quando você precisa construir um pool de recursos caros (como conexões de banco de dados). Você não estaria interessado em criar o pool se ninguém nunca os usar (classe estática significa que você fará o trabalho caro quando a classe for carregada).
fonte
Um singleton também é uma boa ideia se você deseja forçar o armazenamento em cache eficiente dos dados. por exemplo, tenho uma classe que procura definições em um documento xml. Como a análise do documento pode demorar um pouco, configurei um cache de definições (uso SoftReferences para evitar outOfmemeoryErrors). Se a definição desejada não estiver no cache, faço a análise de xml cara. Caso contrário, eu devolvo uma cópia do cache. Já que ter vários caches significaria que eu ainda teria que carregar a mesma definição várias vezes, eu preciso ter um cache estático. Eu escolhi implementar esta classe como um singleton para que eu pudesse escrever a classe usando apenas membros de dados normais (não estáticos). Isso me permite ainda criar uma representação da classe caso eu precise dela por algum motivo (serialização, teste de unidade, etc.)
fonte
Singleton é como um serviço, conforme já mencionado. Pro é sua flexibilidade. Estático, bem, você precisa de algumas partes estáticas para implementar o Singleton.
Singleton possui código para cuidar da instanciação do objeto real, o que pode ser uma grande ajuda se você tiver problemas de corrida. Em uma solução estática, você pode precisar lidar com problemas de corrida em vários locais de código.
No entanto, da mesma forma que Singleton pode ser construído com algumas variáveis estáticas, você pode compará-lo com 'goto'. Ele pode ser muito útil para construir outras estruturas, mas você realmente precisa saber como usá-lo e não deve "abusar" dele. Portanto, a recomendação geral é manter o Singleton e usar a estática se for necessário.
verifique também o outro post: Por que escolher uma classe estática em vez de uma implementação singleton?
fonte
consulte isso
resumo:
uma. Uma regra fácil que você pode seguir é: se não for necessário manter o estado, você pode usar uma classe estática, caso contrário, deve usar um Singleton.
b. use um Singleton se for um objeto particularmente “pesado”. Se o seu objeto for grande e ocupar uma quantidade razoável de memória, muitas chamadas n / w (pool de conexão) ..etc. Para ter certeza de que não será instanciado várias vezes. Uma classe Singleton ajudará a evitar que tal caso aconteça
fonte
Quando a única classe precisa de estado. Singletons mantêm um estado global, classes estáticas não.
Por exemplo, criando um ajudante em torno de uma classe de registro: Se você tiver hive alterável (HKey Current User vs. HKEY Local Machine), você pode ir:
Agora, qualquer outra chamada para aquele singleton irá operar na seção Máquina Local. Caso contrário, usando uma classe estática, você teria que especificar aquela seção da Máquina Local everytiem ou ter um método como
ReadSubkeyFromLocalMachine
.fonte