O padrão Singleton é um membro totalmente integralizado da GoF 's padrões de livro , mas ultimamente parece bastante órfãs pelo mundo do desenvolvedor. Eu ainda uso muitos singletons, especialmente para as classes de fábrica , e embora você precise ter um pouco de cuidado com os problemas de multithreading (como qualquer classe, na verdade), não vejo por que eles são tão terríveis.
O Stack Overflow parece supor que todos concordam que os Singletons são maus. Por quê?
Apoie suas respostas com " fatos, referências ou conhecimentos específicos "
Respostas:
Parafraseado de Brian Button:
Eles geralmente são usados como uma instância global, por que isso é tão ruim? Porque você oculta as dependências do seu aplicativo no seu código, em vez de expô-las através das interfaces. Tornar algo global para evitar distribuir é um cheiro de código .
Eles violam o princípio da responsabilidade única : em virtude de controlarem sua própria criação e ciclo de vida.
Eles inerentemente fazem com que o código seja fortemente acoplado . Isso dificulta a falsificação deles em teste em muitos casos.
Eles carregam o estado durante toda a vida útil do aplicativo. Outro sucesso nos testes, pois você pode acabar com uma situação em que os testes precisam ser solicitados, o que é um grande não para testes de unidade. Por quê? Porque cada teste de unidade deve ser independente do outro.
fonte
Singletons resolvem um (e apenas um) problema.
Contenção de Recursos.
Se você tem algum recurso que
( 1 ) pode ter apenas uma instância e
( 2 ) você precisa gerenciar essa instância única,
você precisa de um singleton .
Não há muitos exemplos. Um arquivo de log é o grande. Você não deseja simplesmente abandonar um único arquivo de log. Você deseja liberar, sincronizar e fechá-lo corretamente. Este é um exemplo de um único recurso compartilhado que precisa ser gerenciado.
É raro você precisar de um singleton. A razão pela qual eles são ruins é que se sentem globais e são membros totalmente pagos do livro GoF Design Patterns .
Quando você pensa que precisa de um ambiente global, provavelmente está cometendo um terrível erro de design.
fonte
Alguns esnobes de codificação os consideram apenas um global glorificado. Da mesma forma que muitas pessoas odeiam a declaração goto , há outras que odeiam a idéia de usar um global . Eu já vi vários desenvolvedores se esforçarem extraordinariamente para evitar uma globalização porque consideravam usar uma como uma admissão de falha. Estranho mas verdade.
Na prática, o padrão Singleton é apenas uma técnica de programação que é uma parte útil do seu conjunto de conceitos. De tempos em tempos, você pode achar que é a solução ideal e, portanto, usá-lo. Mas usá-lo apenas para que você possa se gabar de usar um padrão de design é tão estúpido quanto se recusar a usá-lo, porque é apenas global .
fonte
Misko Hevery, do Google, tem alguns artigos interessantes sobre exatamente esse tópico ...
Singletons são mentirosos patológicos tem um exemplo de teste de unidade que ilustra como os singletons podem dificultar descobrir cadeias de dependência e iniciar ou testar um aplicativo. É um exemplo bastante extremo de abuso, mas o argumento que ele faz ainda é válido:
Onde estão todos os Singletons Gone afirma que a injeção de dependência facilitou a obtenção de instâncias para os construtores que os exigem, o que alivia a necessidade subjacente por trás dos Singletons ruins e globais que foram criticados no primeiro artigo.
fonte
Eu acho que a confusão é causada pelo fato de as pessoas não conhecerem a aplicação real do padrão Singleton. Não posso enfatizar isso o suficiente. Singleton não é um padrão para envolver os globais. O padrão Singleton deve ser usado apenas para garantir que uma e apenas uma instância de uma determinada classe exista durante o tempo de execução.
As pessoas pensam que Singleton é mau porque o estão usando para globais. É por causa dessa confusão que Singleton é menosprezado. Por favor, não confunda Singletons e Globais. Se usado para a finalidade a que se destina, você obterá benefícios extremos com o padrão Singleton.
fonte
setInstance
métodos antes.) Mas isso pouco importa - o fato de que "precisamos" de um singleton também não sabia nada sobre encapsulamento ou o que há de errado com isso. estado global mutável, de modo que ele (?) forneceu prestadores de serviço para todos. solteiro. campo. (E sim, isso acontece. Monte Quase todas as Singleton que eu já vi na natureza era mutável por design, e muitas vezes embarassingly lo..)goto
etc. Eles podem funcionar em muitos casos, mas, francamente, "funciona" não é suficiente - se você quiser ir contra a sabedoria convencional, é melhor demonstrar como sua abordagem é melhor que as soluções convencionais. E ainda não vi esse caso para o padrão Singleton.getInstance
método ou nome semelhante e evita a existência de um segunda instância. Francamente, nesse ponto, você pode nem ter a única instância.Uma coisa bastante ruim sobre singletons é que você não pode estendê-los com muita facilidade. Você basicamente precisa criar algum tipo de padrão decorador ou algo assim, se quiser mudar o comportamento deles. Além disso, se um dia você quiser ter várias maneiras de fazer isso, pode ser um pouco doloroso mudar, dependendo de como você define seu código.
Uma coisa a observar, se você usar singletons, tente passá-los para quem precisar deles, em vez de acessá-los diretamente ... Caso contrário, se você optar por ter várias maneiras de fazer o que o singleton faz, será bastante difícil de mudar, pois cada classe incorpora uma dependência se acessar o singleton diretamente.
Então, basicamente:
ao invés de:
Eu acredito que esse tipo de padrão é chamado injeção de dependência e geralmente é considerado uma coisa boa.
Porém, como qualquer padrão ... Pense sobre isso e considere se o seu uso na situação fornecida é inadequado ou não ... Normalmente, as regras são quebradas e os padrões não devem ser aplicados à toa, sem pensar.
fonte
getInstance()
, então (b) não é mais verdade.getInstance()
, você efetivamente descartou a única diferença útil entre o padrão Singleton e uma referência comum. No que diz respeito ao restante do código, a simplicidade não é mais uma propriedade. Somente o interlocutorgetInstance()
precisa saber ou se importar com quantas instâncias existem. Com apenas um chamador, custa mais esforço e flexibilidade para a classe impor de maneira confiável a singeleza do que fazer com que o chamador simplesmente armazene uma referência e reutilize-a.O padrão singleton não é um problema em si. O problema é que o padrão é frequentemente usado por pessoas que desenvolvem software com ferramentas orientadas a objetos sem ter uma compreensão sólida dos conceitos de OO. Quando singletons são introduzidos nesse contexto, eles tendem a se transformar em classes incontroláveis que contêm métodos auxiliares para pouco uso.
Singletons também são um problema de uma perspectiva de teste. Eles tendem a dificultar a escrita de testes de unidade isolados. Inversão de controle (IoC) e injeção de dependência são padrões destinados a superar esse problema de uma maneira orientada a objetos que se presta a testes de unidade.
Em um ambiente de coleta de lixo, os singletons podem se tornar rapidamente um problema em relação ao gerenciamento de memória.
Há também o cenário multithread em que singletons podem se tornar um gargalo e um problema de sincronização.
fonte
Um singleton é implementado usando um método estático. Os métodos estáticos são evitados por pessoas que fazem testes de unidade porque eles não podem ser ridicularizados ou descartados. A maioria das pessoas neste site são grandes defensores dos testes de unidade. A convenção geralmente mais aceita para evitá-los é usar a inversão do padrão de controle .
fonte
Singleton
classe falsa . No entanto, isso complica imensamente o processo de teste. Por um lado, agora você precisa ser capaz de descarregar as classes à vontade (não é realmente uma opção na maioria dos idiomas) ou iniciar uma nova VM para cada teste (leia: os testes podem levar milhares de vezes mais). Para dois, no entanto, a dependênciaSingleton
é um detalhe de implementação que agora está vazando em todos os seus testes.Singletons também são ruins quando se trata de clustering . Porque então, você não tem "exatamente um singleton" em seu aplicativo.
Considere a seguinte situação: Como desenvolvedor, você deve criar um aplicativo Web que acesse um banco de dados. Para garantir que as chamadas simultâneas ao banco de dados não entrem em conflito, crie um save de thread
SingletonDao
:Portanto, você tem certeza de que existe apenas um singleton no seu aplicativo e todo o banco de dados passa por esse e apenas
SingletonDao
. Seu ambiente de produção agora fica assim:Está tudo bem até agora.
Agora, considere que você deseja configurar várias instâncias do seu aplicativo Web em um cluster. Agora, de repente, você tem algo parecido com isto:
Isso parece estranho, mas agora você tem muitos singletons em seu aplicativo . E é exatamente isso que um singleton não deve ser: ter muitos objetos dele. Isso é especialmente ruim se você, como mostrado neste exemplo, deseja fazer chamadas sincronizadas para um banco de dados.
Obviamente, este é um exemplo de mau uso de um singleton. Mas a mensagem deste exemplo é: Você não pode confiar que exista exatamente uma instância de um singleton em seu aplicativo - especialmente quando se trata de armazenamento em cluster.
fonte
fonte
O monopólio é o diabo e os singletons com estado não-readonly / mutável são o problema "real" ...
Depois de ler Singletons são Mentirosos Patológicos, como sugerido na resposta de Jason, me deparei com este pequeno trecho que fornece o melhor exemplo apresentado de como os singletons são frequentemente mal utilizados.
Na última declaração, ele está se referindo ao conceito do blog de 'singletons são mentirosos'.
Como isso se aplica ao monopólio?
Para iniciar um jogo de monopólio, primeiro:
Agora, para quem realmente não jogou monopólio, esses padrões são ideais na melhor das hipóteses. É difícil engolir uma derrota no monopólio, porque o monopólio é sobre dinheiro; se você perder, terá que observar cuidadosamente o resto dos jogadores terminar o jogo, e as perdas são geralmente rápidas e esmagadoras. Portanto, as regras geralmente são distorcidas em algum momento para servir aos interesses de alguns dos jogadores às custas dos outros.
Então você está jogando monopólio com os amigos Bob, Joe e Ed. Você está rapidamente construindo seu império e consumindo participação de mercado a uma taxa exponencial. Seus oponentes estão enfraquecendo e você começa a cheirar sangue (figurativamente). Seu amigo Bob investiu todo o seu dinheiro no engarrafamento do maior número possível de propriedades de baixo valor, mas ele não está recebendo um alto retorno sobre o investimento da maneira que ele esperava. Bob, como um golpe de má sorte, cai no seu calçadão e é retirado do jogo.
Agora, o jogo vai de dados amigáveis a negócios sérios. Bob foi feito o exemplo do fracasso e Joe e Ed não querem acabar como 'aquele cara'. Então, sendo o principal jogador, você de repente se torna o inimigo. Joe e Ed começam a praticar operações sob a mesa, injeções de dinheiro pelas costas, troca de casas subvalorizada e geralmente qualquer coisa para enfraquecê-lo como jogador até que um deles chegue ao topo.
Então, em vez de um deles vencer, o processo começa tudo de novo. De repente, um conjunto finito de regras se torna um alvo em movimento e o jogo se degenera no tipo de interações sociais que constituiriam a base de todos os reality shows de TV de alta classificação desde o Survivor. Por que, porque as regras estão mudando e não há consenso sobre como / por que / o que eles devem representar e, mais importante, não há ninguém tomando as decisões. Todo jogador do jogo, nesse ponto, está fazendo suas próprias regras e caos, até que dois jogadores estejam cansados demais para manter a farsa e desistir lentamente.
Portanto, se um livro de regras para um jogo representasse com precisão um singleton, o livro de regras do monopólio seria um exemplo de abuso.
Como isso se aplica à programação?
Além de todos os problemas óbvios de segurança de encadeamento e sincronização que os singletons mutáveis apresentam ... Se você possui um conjunto de dados, ele pode ser lido / manipulado por várias fontes diferentes simultaneamente e existe durante a vida útil da execução do aplicativo, provavelmente é um bom momento para voltar atrás e perguntar "estou usando o tipo certo de estrutura de dados aqui".
Pessoalmente, eu vi um programador abusar de um singleton usando-o como uma espécie de armazenamento de banco de dados de threads cruzados dentro de um aplicativo. Tendo trabalhado diretamente no código, posso atestar que foi um processo lento (por causa de todos os bloqueios de thread necessários para torná-lo seguro) e um pesadelo para trabalhar (por causa da natureza imprevisível / intermitente dos erros de sincronização) e quase impossível testar em condições de 'produção'. Certamente, um sistema poderia ter sido desenvolvido usando pesquisa / sinalização para superar alguns dos problemas de desempenho, mas isso não resolveria os problemas com testes e por que se preocupar quando um banco de dados 'real' já pode realizar a mesma funcionalidade de uma maneira muito mais robusta / maneira escalável.
Um Singleton é apenas uma opção se você precisar do que um Singleton fornece. Uma instância de somente leitura de um objeto. Essa mesma regra deve cascata para as propriedades / membros do objeto também.
fonte
Singleton.getInstance()
. Um idioma que ofereça suporte à reflexão pode solucionar esse problema, definindo o campo em que a One True Instance está armazenada. Os testes da OMI, no entanto, tornam-se um pouco menos confiáveis depois que você começa a brincar com o estado privado de outra classe.Singleton não é uma instância única!
Ao contrário de outras respostas, não quero falar sobre o que há de errado com os Singletons, mas mostrar como eles são poderosos e impressionantes quando usados da maneira certa!
Solução : Use um processo de inicialização por thread único para inicializar todas as dependências do seu singleton.
Solução : Use o método Padrão de fábrica para zombar
Você pode mapear
MyModel
para aTestMyModel
classe que a herda; em todos os lugares emMyModel
que será injetado, você seráTestMyModel
instruído. - Problema : singletons podem causar vazamento de memória, pois nunca foram descartados.Solução : Bem, descarte-os! Implemente um retorno de chamada em seu aplicativo para descartar corretamente os singletons; remova todos os dados vinculados a eles e, finalmente: remova-os da fábrica.
Como afirmei no título singleton, não se trata de instância única.
fonte
Settings
objeto singleton acessível a partir de qualquer widget, para que cada widget saiba como formatar os números exibidos. Se não fosse um objeto acessível globalmente, eu teria que injetá-lo no construtor para cada widget do construtor e manter a referência a ele como uma variável de membro. Isso é um terrível desperdício de memória e tempo.Minha resposta sobre como os Singletons são ruins é sempre "eles são difíceis de fazer o certo". Muitos dos componentes fundamentais das linguagens são singletons (classes, funções, namespaces e até operadores), assim como os componentes de outros aspectos da computação (host local, rota padrão, sistema de arquivos virtual etc.), e não é por acaso. Embora causem problemas e frustrações de tempos em tempos, também podem fazer muitas coisas funcionarem MUITO melhor.
Os dois maiores erros que vejo são: tratá-lo como um global e não definir o fechamento de Singleton.
Todo mundo fala sobre Singleton como globais, porque basicamente são. No entanto, grande parte (infelizmente, não todas) da maldade em um global não provém intrinsecamente de ser global, mas de como você a usa. O mesmo vale para Singletons. Na verdade, mais do que "instância única" realmente não precisa significar "acessível globalmente". É mais um subproduto natural e, dado o mal que sabemos disso, não devemos ter tanta pressa de explorar a acessibilidade global. Depois que os programadores veem um Singleton, eles parecem sempre acessá-lo diretamente por meio de seu método de instância. Em vez disso, você deve navegar para ele como faria com qualquer outro objeto. A maioria dos códigos nem deveria estar ciente de que está lidando com um Singleton (acoplamento flexível, certo?). Se apenas um pequeno pedaço de código acessar o objeto como se fosse global, muitos danos serão desfeitos.
O contexto Singleton também é realmente importante. A característica definidora de um Singleton é que existe "apenas um", mas a verdade é que é "apenas um" dentro de algum tipo de contexto / espaço de nome. Eles geralmente são um dos seguintes: um por encadeamento, processo, endereço IP ou cluster, mas também podem ser um por processador, máquina, espaço para nome do idioma / carregador de classes / qualquer que seja, sub-rede, Internet etc.
O outro erro, menos comum, é ignorar o estilo de vida de Singleton. Só porque existe apenas um, não significa que um Singleton seja onipotente "sempre foi e sempre será", nem é geralmente desejável (objetos sem início e fim violam todos os tipos de suposições úteis no código e devem ser empregados apenas nas mais desesperadas circunstâncias.
Se você evitar esses erros, os Singletons ainda podem ser uma PITA, mas estão prontos para ver que muitos dos piores problemas são significativamente mitigados. Imagine um Java Singleton, definido explicitamente como uma vez por carregador de classe (o que significa que precisa de uma política de segurança de encadeamento), com métodos definidos de criação e destruição e um ciclo de vida que determina quando e como eles são chamados e cujo método de "instância" foi proteção de pacote, para que geralmente seja acessada por outros objetos não globais. Ainda é uma fonte potencial de problemas, mas certamente muito menos problemas.
Infelizmente, ao invés de ensinar bons exemplos de como fazer Singletons. Ensinamos exemplos ruins, deixamos que os programadores fiquem usando-os por um tempo e depois dizemos que eles são um padrão de design ruim.
fonte
Consulte a Wikipedia Singleton_pattern
Referências (apenas referências relevantes do artigo)
fonte
Não é que os singletons sejam ruins, mas o padrão de design do GoF é. O único argumento realmente válido é que o padrão de design do GoF não se presta em relação aos testes, especialmente se os testes forem executados em paralelo.
O uso de uma única instância de uma classe é uma construção válida, desde que você aplique os seguintes meios no código:
Verifique se a classe que será usada como um singleton implementa uma interface. Isso permite que stubs ou zombarias sejam implementados usando a mesma interface
Verifique se o Singleton é seguro para threads. Isso é um dado.
O singleton deve ser simples por natureza e não excessivamente complicado.
Durante o tempo de execução do aplicativo, em que os singletons precisam ser passados para um determinado objeto, use uma fábrica de classes que construa esse objeto e faça com que a fábrica passe a instância singleton para a classe que precisa.
Durante o teste e para garantir um comportamento determinístico, crie a classe singleton como uma instância separada como a própria classe ou um esboço / simulação que implemente seu comportamento e passe-o como está para a classe que o exige. Não use o fator de classe que cria o objeto em teste que precisa do singleton durante o teste, pois ele passará na única instância global dele, o que anula o objetivo.
Usamos Singletons em nossas soluções com bastante sucesso testável, garantindo um comportamento determinístico em fluxos de execução de testes paralelos.
fonte
Eu gostaria de abordar os 4 pontos na resposta aceita, espero que alguém possa explicar por que estou errado.
Por que ocultar dependências no seu código é ruim? Já existem dezenas de dependências ocultas (chamadas em tempo de execução C, chamadas à API do SO, chamadas de funções globais) e dependências singleton são fáceis de encontrar (procure por exemplo ()).
"Tornar algo global para evitar distribuir é um cheiro de código". Por que não passar algo ao redor para evitar torná-lo um singleton com cheiro de código?
Se você está passando um objeto por 10 funções em uma pilha de chamadas apenas para evitar um singleton, isso é ótimo?
Princípio da responsabilidade única: acho que isso é um pouco vago e depende da sua definição de responsabilidade. Uma pergunta relevante seria: por que adicionar essa "responsabilidade" específica a uma questão de classe?
Por que passar um objeto para uma classe o torna mais fortemente acoplado do que usá-lo como um singleton dentro da classe?
Por que muda quanto tempo o estado dura? Singletons podem ser criados ou destruídos manualmente, para que o controle ainda esteja lá, e você pode tornar o tempo de vida igual ao tempo de vida de um objeto não-singleton.
Em relação aos testes de unidade:
fonte
Vince Huston tem esses critérios, que me parecem razoáveis:
fonte
Singletons são ruins do ponto de vista purista.
Do ponto de vista prático, um singleton é um trade-off entre desenvolvimento e complexidade .
Se você sabe que seu aplicativo não vai mudar muito, eles são bastante aceitáveis. Saiba que você pode precisar refatorar as coisas se seus requisitos mudarem de maneira inesperada (o que é bastante bom na maioria dos casos).
Singletons às vezes também complicam o teste de unidade .
fonte
Não há nada inerentemente errado com o padrão, supondo que ele esteja sendo usado para algum aspecto do seu modelo que seja verdadeiramente único.
Acredito que a reação se deve ao uso excessivo, que, por sua vez, se deve ao fato de ser o padrão mais fácil de entender e implementar.
fonte
Não vou comentar sobre o argumento do bem / do mal, mas não os uso desde a primavera . O uso da injeção de dependência removeu praticamente meus requisitos para singleton, servicelocators e fábricas. Acho esse ambiente muito mais produtivo e limpo, pelo menos para o tipo de trabalho que eu faço (aplicativos da Web baseados em Java).
fonte
Singleton é um padrão e pode ser usado ou abusado como qualquer outra ferramenta.
A parte ruim de um singleton geralmente é o usuário (ou devo dizer o uso inadequado de um singleton para coisas que ele não foi projetado para fazer). O maior infrator está usando um singleton como uma variável global falsa.
fonte
Quando você escreve código usando singletons, digamos, um logger ou uma conexão com o banco de dados, e depois descobre que precisa de mais de um log ou mais de um banco de dados, você está com problemas.
Singletons tornam muito difícil passar deles para objetos comuns.
Além disso, é muito fácil escrever um singleton não seguro para threads.
Em vez de usar singletons, você deve passar todos os objetos utilitários necessários de uma função para outra. Isso pode ser simplificado se você agrupar todos eles em um objeto auxiliar, como este:
fonte
Os problemas com singletons são a questão do escopo aumentado e, portanto, do acoplamento . Não há como negar que existem algumas situações em que você precisa acessar uma única instância e isso pode ser realizado de outras maneiras.
Agora eu prefiro projetar em torno de um contêiner de inversão de controle (IoC) e permitir que a vida útil seja controlada pelo contêiner. Isso dá a você o benefício das classes que dependem da instância de não terem conhecimento do fato de que existe uma única instância. A vida útil do singleton pode ser alterada no futuro. Uma vez que esse exemplo que encontrei recentemente foi um ajuste fácil de thread único para multi-thread.
FWIW, se for um PIA quando você tentar fazer o teste de unidade, ele será PIA quando você tentar depurar, corrigir erros ou aprimorá-lo.
fonte
Artigo recente sobre esse assunto por Chris Reath na Coding Without Comments .
Nota: A codificação sem comentários não é mais válida. No entanto, o artigo ao qual está sendo vinculado foi clonado por outro usuário.
http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx
fonte
Singletons NÃO são ruins. Só é ruim quando você cria algo globalmente único que não é globalmente único.
No entanto, existem "serviços de escopo de aplicativos" (pense em um sistema de mensagens que faz com que os componentes interajam) - solicita uma classe de singleton, "MessageQueue" - que possui o método "SendMessage (...)".
Você pode fazer o seguinte em todo o lugar:
MessageQueue.Current.SendMessage (new MailArrivedMessage (...));
E, é claro, faça:
MessageQueue.Current.RegisterReceiver (this);
nas classes que implementam IMessageReceiver.
fonte
Muitas pessoas colocam objetos que não são seguros para threads em um padrão único. Eu já vi exemplos de um DataContext ( LINQ to SQL ) feito em um padrão singleton, apesar do DataContext não ser seguro para threads e é puramente um objeto de unidade de trabalho.
fonte
Aqui está mais uma coisa sobre singletons que ninguém disse ainda.
Na maioria dos casos, "singletonidade" é um detalhe de implementação para alguma classe, e não uma característica de sua interface. Inversão do contêiner de controle pode ocultar essa característica dos usuários da classe; você só precisa marcar sua classe como um singleton (com
@Singleton
anotação em Java, por exemplo) e é isso; IoCC fará o resto. Você não precisa fornecer acesso global à sua instância de singleton porque o acesso já é gerenciado pelo IoCC. Portanto, não há nada errado com os singletons da IoC.Os Singletons do GoF em oposição ao IoC Os Singletons devem expor "singletonidade" na interface através do método getInstance () e, portanto, sofrem com tudo o que foi dito acima.
fonte
Singletons não são maus, se você usá-lo corretamente e minimamente . Existem muitos outros bons padrões de design que substituem as necessidades do singleton em algum momento (e também oferecem melhores resultados). Mas alguns programadores desconhecem esses bons padrões e usam o singleton para todos os casos, o que torna o singleton ruim para eles.
fonte
Em primeiro lugar, uma classe e seus colaboradores devem primeiro executar seu propósito pretendido, em vez de se concentrar nos dependentes. O gerenciamento do ciclo de vida (quando as instâncias são criadas e quando estão fora do escopo) não deve fazer parte da responsabilidade das classes. A melhor prática aceita para isso é criar ou configurar um novo componente para gerenciar dependências usando injeção de dependência.
Freqüentemente, o software fica mais complicado, faz sentido ter várias instâncias independentes da classe Singleton com diferentes estados. Confirmar código para simplesmente pegar o singleton está errado nesses casos. Usando
Singleton.getInstance()
pode ser bom para pequenos sistemas simples, mas não funciona / dimensiona quando é necessário uma instância diferente da mesma classe.Nenhuma classe deve ser considerada um singleton, mas sim uma aplicação de seu uso ou de como é usada para configurar dependentes. Para um processo rápido e desagradável, isso não importa - basta codificar como o caminho dos arquivos não importa, mas para aplicativos maiores essas dependências precisam ser fatoradas e gerenciadas de maneira mais apropriada usando o DI.
Os problemas que os singleton causam nos testes são um sintoma de seu caso / ambiente de uso único codificado. O conjunto de testes e os vários testes são individuais e separam algo que não é compatível com a codificação embutida de um singleton.
fonte
Como são basicamente variáveis globais orientadas a objetos, você geralmente pode projetar suas classes de forma a não precisar delas.
fonte