Vamos encarar. O Singleton Pattern é um tópico altamente controverso com hordas de programadores em ambos os lados da cerca. Há aqueles que acham que o Singleton nada mais é do que uma variável global glorificada, e outros que juram pelo padrão e o usam incessantemente. Não quero que a controvérsia do Singleton esteja no centro da minha pergunta, entretanto. Todos podem ter um cabo de guerra e batalhar para ver quem vence por mim . O que estou tentando dizer é que não acredito que haja uma única resposta correta e não estou intencionalmente tentando inflamar disputas partidárias. Estou simplesmente interessado em alternativas singleton quando faço a pergunta:
Existem alternativas específicas para o GOF Singleton Pattern?
Por exemplo, muitas vezes, quando usei o padrão singleton no passado, estou simplesmente interessado em preservar o estado / valores de uma ou várias variáveis. O estado / valores das variáveis, entretanto, podem ser preservados entre cada instanciação da classe usando variáveis estáticas em vez de usar o padrão singleton.
Que outra ideia você tem?
EDIT: Eu realmente não quero que este seja outro post sobre "como usar o singleton corretamente." Novamente, estou procurando maneiras de evitá-lo. Para se divertir, ok? Acho que estou fazendo uma pergunta puramente acadêmica na voz de seu melhor trailer de filme: "Em um universo paralelo onde não há um único, o que poderíamos fazer?"
fonte
Respostas:
Alex Miller em " Patterns I Hate " cita o seguinte:
"Quando um singleton parece ser a resposta, acho muitas vezes mais sensato:
fonte
Para entender a maneira adequada de contornar os Singletons, você precisa entender o que há de errado com os Singletons (e o estado global em geral):
Singletons ocultam dependências.
Por que isso é importante?
Porque se você ocultar as dependências, você tende a perder o controle da quantidade de acoplamento.
Você pode argumentar que
é mais simples que
mas pelo menos a segunda API deixa claro exatamente quais são os colaboradores do método.
Portanto, a maneira de contornar os Singletons não é usar variáveis estáticas ou localizadores de serviço, mas alterar as classes Singleton em instâncias, que são instanciadas no escopo onde fazem sentido e injetadas nos componentes e métodos que precisam delas. Você pode usar um framework IoC para lidar com isso, ou você pode fazer isso manualmente, mas o importante é se livrar do seu estado global e tornar as dependências e colaborações explícitas.
fonte
A melhor solução que encontrei é usar o padrão de fábrica para construir instâncias de suas classes. Usando o padrão, você pode garantir que haja apenas uma instância de uma classe que é compartilhada entre os objetos que a usam.
Achei que seria complicado de gerenciar, mas depois de ler esta postagem do blog "Para onde foram todos os solteiros?" , parece tão natural. E como um aparte, isso ajuda muito a isolar seus testes de unidade.
Em resumo, o que você precisa fazer? Sempre que um objeto depende de outro, ele receberá uma instância dele apenas por meio de seu construtor (nenhuma palavra-chave nova em sua classe).
E então, a fábrica.
Como você irá instanciar sua fábrica apenas uma vez, haverá uma única instanciação de exSingleton. Sempre que você chamar buildNeedy, a nova instância de NeedyClass será empacotada com exSingleton.
Eu espero que isso ajude. Por favor, indique quaisquer erros.
fonte
Spring ou qualquer outro IoC-Container faz um trabalho razoavelmente bom nisso. Como as classes são criadas e gerenciadas fora do próprio aplicativo, o contêiner pode criar singletons de classes simples e injetá-los onde necessário.
fonte
Você não deveria ter que sair do seu caminho para evitar qualquer padrão. O uso de um padrão é uma decisão de design ou um ajuste natural (ele simplesmente se encaixa). Ao projetar um sistema, você tem a opção de usar um padrão ou não usá-lo. No entanto, você não deve sair de seu caminho para evitar qualquer coisa que seja, em última análise, uma escolha de design.
Não evito o Padrão Singleton. Ou é apropriado e eu uso ou não é apropriado e eu não uso. Acredito que seja simples assim.
A adequação (ou falta dela) do Singleton depende da situação. É uma decisão de design que deve ser tomada e as consequências dessa decisão devem ser compreendidas (e documentadas).
fonte
Monostate (descrito no Agile Software Development de Robert C. Martin) é uma alternativa ao singleton. Nesse padrão, os dados da classe são todos estáticos, mas os getters / setters não são estáticos.
Por exemplo:
Monostate tem comportamento semelhante ao singleton, mas o faz de uma maneira em que o programador não está necessariamente ciente do fato de que um singleton está sendo usado.
fonte
O padrão singleton existe porque há situações em que um único objeto é necessário para fornecer um conjunto de serviços .
Mesmo se esse for o caso, ainda considero inadequada a abordagem de criar singletons usando um campo / propriedade estática global que representa a instância. É impróprio porque cria uma dependência no código entre o campo estático e o objeto não, os serviços que o objeto fornece.
Portanto, em vez do padrão clássico, singleton, recomendo usar o padrão de serviço 'like' com contêineres atendidos , onde em vez de usar seu singleton por meio de um campo estático, você obtém uma referência a ele por meio de um método solicitando o tipo de serviço necessário.
em vez de global único
Dessa forma, quando você quiser alterar o tipo de um objeto de singleton para outra coisa, terá um tempo fácil para fazer isso. Além disso, como um benefício adicional, você não precisa passar todas as instâncias de objeto para cada método.
Veja também Inversão de controle , a ideia é que, ao expor singletons diretamente ao consumidor, você cria uma dependência entre o consumidor e a instância do objeto, não os serviços de objeto fornecidos pelo objeto.
Minha opinião é esconder o uso do padrão singleton sempre que possível, porque nem sempre é possível evitá-lo, ou desejável.
fonte
Se você estiver usando um Singleton para representar um único objeto de dados, poderá, em vez disso, passar um objeto de dados como um parâmetro de método.
(embora eu diria que esta é a maneira errada de usar um Singleton em primeiro lugar)
fonte
Se o seu problema é que você deseja manter o estado, você deseja uma classe MumbleManager. Antes de começar a trabalhar com um sistema, seu cliente cria um MumbleManager, onde Mumble é o nome do sistema. O estado é retido por meio disso. Provavelmente, seu MumbleManager conterá uma sacola de propriedades que contém seu estado.
Este tipo de estilo parece muito com o C e não muito com o objeto - você descobrirá que os objetos que definem seu sistema terão uma referência ao mesmo MumbleManager.
fonte
Use um objeto simples e um objeto fábrica. A fábrica é responsável por policiar a instância e os detalhes do objeto simples apenas com as informações de configuração (que contém, por exemplo) e comportamento.
fonte
Na verdade, se você projetar do zero para evitar Singeltons, pode não ter que contornar o problema de não usar Singletons usando variáveis estáticas. Ao usar variáveis estáticas, você também está criando um Singleton mais ou menos, a única diferença é que você está criando diferentes instâncias de objeto, porém internamente todos eles se comportam como se estivessem usando um Singleton.
Você pode dar um exemplo detalhado onde usa um Singleton ou onde um Singleton é usado atualmente e você está tentando evitar usá-lo? Isso poderia ajudar as pessoas a encontrar uma solução mais sofisticada como a situação poderia ser tratada sem um Singleton.
Aliás, eu pessoalmente não tenho problemas com Singletons e não consigo entender os problemas que outras pessoas têm em relação a Singletons. Não vejo nada de ruim neles. Isto é, se você não está abusando deles. Toda técnica útil pode ser abusada e, se for abusada, levará a resultados negativos. Outra técnica comumente mal utilizada é a herança. Ainda assim, ninguém diria que herança é algo ruim só porque algumas pessoas abusam dela terrivelmente.
fonte
Pessoalmente, para mim, uma maneira muito mais sensata de implementar algo que se comporta como um singleton é usar uma classe totalmente estática (membros estáticos, métodos estáticos, propriedades estáticas). Na maioria das vezes eu o implemento desta forma (não consigo pensar em nenhuma diferença de comportamento do ponto de vista do usuário)
fonte
Acho que o melhor lugar para policiar o singleton é no nível de design da classe. Nesse estágio, você deve ser capaz de mapear as interações entre as classes e ver se algo absolutamente, definitivamente requer que apenas 1 instância dessa classe exista em qualquer momento da vida do aplicativo.
Se for esse o caso, então você tem um singleton. Se você está adicionando singletons como uma conveniência durante a codificação, então você realmente deve revisitar seu design e também parar de codificar os referidos singletons :)
E sim, 'polícia' é a palavra que eu quis dizer aqui, em vez de 'evitar'. O singleton não é algo a ser evitado (da mesma forma que goto e variáveis globais não são algo a ser evitado). Em vez disso, você deve monitorar seu uso e garantir que é o melhor método para fazer o que deseja com eficácia.
fonte
Eu uso o singleton principalmente como "contêiner de métodos", sem nenhum estado. Se eu precisar compartilhar esses métodos com muitas classes e quiser evitar a carga de instanciação e inicialização, crio um contexto / sessão e inicializo todas as classes lá; tudo o que se refere à sessão também tem acesso ao "singleton" nele contido.
fonte
Não tendo programado em um ambiente intensamente orientado a objetos (por exemplo, Java), não estou completamente informado sobre os meandros da discussão. Mas eu implementei um singleton no PHP 4. Eu fiz isso como uma forma de criar um manipulador de banco de dados 'caixa preta' que inicializava automaticamente e não precisava passar por chamadas de função para cima e para baixo em uma estrutura incompleta e um tanto quebrada.
Depois de ler alguns links de padrões singleton, não tenho certeza se iria implementá-los exatamente da mesma maneira novamente. O que era realmente necessário eram vários objetos com armazenamento compartilhado (por exemplo, o identificador de banco de dados real) e isso é basicamente o que minha chamada se tornou.
Como a maioria dos padrões e algoritmos, usar um singleton 'apenas porque é legal' é The Wrong Thing To Do. Eu precisava de uma chamada verdadeiramente 'caixa-preta' que parecia muito com um singleton. E, IMO, essa é a maneira de lidar com a questão: esteja ciente do padrão, mas também observe seu escopo mais amplo e em que nível sua instância precisa ser única.
fonte
O que você quer dizer com quais são as minhas técnicas para evitá-lo?
Para "evitá-lo", isso implica que há muitas situações que encontro nas quais o padrão singleton é um ajuste naturalmente bom e, portanto, tenho que tomar algumas medidas para neutralizar essas situações.
Mas não existem. Não tenho que evitar o padrão singleton. Simplesmente não surge.
fonte