Pergunta

Quando você não deve usar uma classe singleton embora possa ser muito tentador para fazê-lo? Seria muito bom se tivéssemos uma lista da maioria de exemplos comuns de 'singletonitis' que devemos ter o cuidado de evitar.

Foi útil?

Solução

Não use um singleton para algo que pode evoluir para um recurso multiplicável.

Isso provavelmente soa bobo, mas se você declarar algo um singleton que você está fazendo uma declaração muito forte que é absolutamente único. Você está construindo código em torno dele, mais e mais. E quando você, em seguida, descobrir depois de milhares de linhas de código que não é um singleton em tudo, você tem uma enorme quantidade de trabalho na frente de você, porque todos os outros objetos esperar "o" objeto sagrado da classe WizBang ser um singleton .

Exemplo típico: "Há apenas uma conexão com o banco esta aplicação tem, portanto, é um singleton." - Péssima ideia. Você pode querer ter várias conexões no futuro. Melhor criar um pool de conexões de banco de dados e preenchê-lo com apenas uma instância. Age como um Singleton, mas todos os outros códigos terá código growable para acessar a piscina.

EDIT: Eu entendo que, teoricamente, você pode estender um singleton em vários objetos. No entanto, não há nenhum ciclo de vida real (como pooling / unpooling), que significa que não há uma verdadeira apropriação dos objetos que foram entregues, ou seja, o agora multi-singleton teria que ser sem estado para ser usado simultaneamente por diferentes métodos e threads.

Outras dicas

singletons bem para a maior parte está apenas fazendo coisas estática de qualquer maneira. Então, ou você está no efeito tornar os dados global, e todos nós sabemos variáveis ??globais são ruins ou você está métodos estáticos escrita e isso não é muito OO agora é?

Aqui é um discurso retórico mais detalhada sobre por que singletons são ruins, por Steve Yegge. Basicamente, você não deve usar singletons em quase todos os casos, você não pode realmente saber que isso nunca vai ser necessário em mais de um lugar.

Eu sei que muitos têm respondido com "quando você tem mais de um", etc.

Uma vez que o poster original queria uma lista de casos em que você não deve usar Singletons (ao invés da razão superior), eu gritei com:

Sempre que você está usando, porque você não tem permissão para usar um global!

O número de vezes que eu tive um engenheiro júnior que tenha usado um Singleton porque sabiam que eu não aceitei globals em revisões de código. Eles muitas vezes parecem chocados quando eu salientar que todos eles fizeram foi substituir um global com um padrão Singleton e eles ainda só tem uma! Mundial

Eu sou culpado de um grande problema de alguns anos atrás (felizmente eu aprendi minha lession desde então).

O que aconteceu é que eu vim a bordo de um projeto de aplicativo de desktop que havia se convertido ao .Net de VB6, e foi uma verdadeira bagunça. Coisas como 40 páginas funções (impressos) e nenhuma estrutura de classe real. Eu construí uma classe para acesso encapsular ao banco de dados. Não uma camada de dados real (ainda), apenas uma classe base que a camada de dados real pode usar. Em algum lugar eu tive a brilhante idéia de fazer esta classe um singleton. Funcionou bem para um ano ou mais, e então nós necessário para construir uma interface web para o aplicativo também. O singleton acabou sendo um enorme gargalo para o banco de dados, uma vez que todos os usuários da Internet tinha que compartilhar a mesma conexão. Mais uma vez ... lição aprendida.

Olhando para trás, provavelmente, na verdade, foi a escolha certa por um tempo curto, uma vez que obrigou os outros desenvolvedores para ser mais disciplinado em usá-lo e fez-los cientes de escopo questões não previamente um problema no mundo do VB6. Mas eu deveria ter mudado de volta após algumas semanas antes tínhamos muito construídas em torno dela.

Aqui está uma discurso pelo meu amigo Alex Miller ... ele não é exatamente enumerar "quando você não deve usar um singleton", mas é uma forma abrangente, excelente post e argumenta que só se deve usar um singleton em casos raros, se em tudo.

Singletons são praticamente sempre uma má idéia e / redundante geralmente inútil, uma vez que são apenas uma simplificação muito limitado de um padrão decente.

Olhe para cima como Dependency Injection funciona. Ele resolve os mesmos problemas, mas de uma forma muito mais útil -. Na verdade, você encontrá-lo se aplica a muitas mais partes do seu projeto

Embora você possa encontrar bibliotecas DI lá fora, você também pode rolar um básico mesmo, é muito fácil.

Eu tento ter apenas um Singleton -. Uma inversão de objeto localizador de controle / serviço

IService service = IoC.GetImplementationOf<IService>();

Uma das coisas que tendem a torná-lo um pesadelo é se ele contém Estado modificável global. Eu trabalhei em um projeto onde houve Singletons utilizado em todo o lugar para as coisas que deveria ter sido resolvido de uma maneira completamente diferente (passar em estratégias etc.) O "de-singletonification" era, em alguns casos, uma grande reescrita de partes da sistema. Eu diria que na parte maior dos casos quando as pessoas usam um Singleton, é simplesmente errado b / c parece bom, em primeiro lugar, mas se transforma em um problema especialmente no teste.

Quando você tem múltiplas aplicações rodando na mesma JVM.

Um singleton é um singleton em toda a JVM, e não apenas uma única aplicação. Mesmo que vários segmentos ou aplicações parece estar criando um novo objeto Singleton, eles estão todos usando a mesma se eles correm na mesma JVM.

Às vezes, você assume haverá apenas um de uma coisa, então você vir a ser errado.

exemplo, uma classe de base de dados. Você supor que você só vai se conectar ao banco de dados do aplicativo.

// Its our database! We'll never need another
class Database
{
};

Mas espere! Seu chefe diz, ligar para algum outro banco de dados caras. Digamos que você queira adicionar phpbb para o site e gostaria de picar seu banco de dados para integrar algumas das suas funcionalidades. Devemos fazer um novo exclusivo ou outra instância do banco de dados? A maioria das pessoas concorda que é preferível uma nova instância da mesma classe, não há duplicação de código.

Você prefere ter

Database ourDb;
Database otherDb;

de copy-passado de banco de dados e fazer:

// Copy-pasted from our home-grown database.
class OtherGuysDatabase
{
};

A ladeira escorregadia aqui é que você pode parar de pensar sobre fazer nova instância das classes e, em vez começar a pensar o seu ok para ter um tipo por cada instância.

No caso de uma conexão (por exemplo), faz sentido que você não gostaria de fazer a conexão em si um singleton, você pode precisar de quatro conexões, ou você pode precisar de destruir e recriar a ligação de um número de vezes.

Mas por que não você acesso todas as suas conexões através de uma única interface (ou seja, gerenciador de conexões)?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top