É uma má idéia criar uma classe que terá apenas uma instância?

9

É uma prática / design ruim de codificação criar uma classe que será instanciada apenas uma vez?

Eu tenho algumas variáveis ​​e funções que podem ser agrupadas em uma classe para "parecerem boas" (por falta de uma descrição melhor), pois elas são um pouco relacionadas, mas podem ser apenas variáveis ​​globais e funções globais.

(Btw, estou usando JavaScript, AngularJS, Express, MongoDB.)

Alice
fonte
2
Talvez você precise de uma aula de Singleton. No entanto, é uma má ideia vincular em uma classe coisas que não estão relacionadas adequadamente.
amigos estão dizendo sobre neonglow
2
Padrão Singleton é ruim. Às vezes, uma instância única é a solução correta.
Bryan Chen #
4
Nem "Singleton" nem "Instância única" são uma boa solução para agrupar coisas globais "apenas um pouco relacionadas" - quando ouço essa descrição, tomo isso sempre como um sinal de aviso. Mas, para lhe dar uma resposta séria, você deve nos contar alguns exemplos das variáveis ​​e funções que você irá agrupar (com seus nomes e significado reais).
Doc Brown
2
O padrão Singleton não é ruim necessariamente. É só que ele tende a ser usado em excesso.
Stephen
É tecnicamente possível aplicar um Singleton em JavaScript?
quer

Respostas:

10

Uma única instância para uma classe faz sentido se o objeto representar um único recurso, como uma conexão Ethernet ou o gerenciador de tarefas do sistema operacional, por exemplo.

As funções são colocadas em uma classe apenas se elas agirem sobre as variáveis ​​das instâncias dessa classe; caso contrário, o mantenedor ficará confuso sobre a intenção dessa classe.

Geralmente, existe um bom motivo para o seu aplicativo ter variáveis ​​globais. Tente encontrar o objetivo comum deles e crie uma classe em torno desse objetivo. Isso não apenas tornará o design claro, mas também sua mente.

mouviciel
fonte
2
+1, mas gostaria de acrescentar: "se o único objetivo comum é que essas variáveis sejam globais, é melhor deixá-las em classes diferentes".
quer
13

Não há problema em escrever uma classe que acaba sendo instanciada apenas uma vez.

Se juntar algumas variáveis ​​e funções dentro de uma classe faz sentido, tem valor semântico ou torna o código mais fácil de ler e manipular, então os mantenedores serão gratos.

O que pode estar muito errado, porém, é reforçar a singularidade por dentro.

Muitas pessoas tendem a disparar o padrão singleton assim que pensam que precisam apenas de uma instância de algo. Veja, por exemplo, como você não descreveu seu contexto em profundidade, mas a maioria das respostas já sugere que você use um singleton. E então o design pode ser danificado, porque se você precisar de outra instância em algum momento por qualquer motivo, a classe impedirá que você faça isso sem alterar muito código.

Portanto, como conclusão, uma instância é boa, mas saiba se:

  1. você só precisa de uma instância ou
  2. você não pode ter mais de uma instância (um caso muito, muito raro na minha experiência).
Julien Guertault
fonte
1
re: # 2, acho que isso nunca é válido. Mesmo que seu objeto seja um NuclearPowerStationCentralCommandController e você só tenha uma central nuclear, você não está dizendo sério que não possui um MockNuclearPowerStationCentralCommandController para teste, não é?
Phoshi
Um problema mais sério, mas menos óbvio, é que, se você precisa de uma implementação ligeiramente diferente do Singleton, não é possível na maioria dos idiomas, porque a maneira como você obtém o Singleton é ir diretamente a ele, em vez de passar a instância .
Amy Blankenship
@ Phoshi: Se apenas alguma coisa pode existir, o código pode usá-la sem ter que manter uma referência. Se houver a possibilidade de existir várias instâncias, os consumidores terão que manter referências a elas. Isso não apenas aumenta os requisitos de armazenamento do objeto, mas os consumidores não poderão mais assumir que outros consumidores manterão uma referência ao mesmo objeto. Isso adiciona uma complexidade considerável. Se a complexidade acabar sendo necessária, é melhor adicioná-la mais cedo ou mais tarde, mas se não for necessária, é melhor evitar.
Supercat
@ supercat: Adicionar o valor de uma referência ao uso de memória é totalmente irrelevante para a esmagadora maioria dos casos, não acho que seja uma boa razão para evitar DI. Você está certo que não pode assumir que todos tenham mais a mesma instância - você não deveria, isso não deveria importar. Não importa se todo mundo tem uma instância diferente, desde que a semântica da interface seja mantida. De qualquer forma, como eu disse, você nunca terá apenas uma instância. Você tem pelo menos mais um para testes e deseja realmente arriscar a suposição de que seus requisitos nunca serão alterados?
Phoshi 17/03/14
@ Phoshi: O uso da memória não é o problema; o problema é que se adiciona outra maneira pela qual os objetos podem diferir. Considere, por exemplo, o que significa que os itens em duas instâncias Dictionary<TKey,KTValue>sejam distintos. Se todas as instâncias de uma Dictionary<TKey,KTValue>instância usam o mesmo IEqualityComparer, não há ambiguidade, mas se elas podem usar comparadores diferentes que definem diferentes relações de equivalência, não sei se é possível definir a.ContentsDistinctFrom(b)com sensibilidade para sempre igual b.ContentsDistinctFrom(a).
precisa
3

É uma prática / design ruim de codificação criar uma classe que será instanciada apenas uma vez?

Não, mesmo que apenas instanciado uma vez, você precisa de uma classe para isso. Mas não pense que você sempre precisará apenas de uma instância, agora e no futuro.

Suponha que você faça um jogo e tenha uma classe de jogadores:

class Player {
    ...
}

Você instancia uma classe de jogador no seu jogo e usa sempre o mesmo objeto. Nada de errado com isso.

No entanto, não faça dele um Singleton! Hoje você cria seu jogo e pensa: "Bem, sempre será um jogo para um jogador. Vou usar um Singleton para meu jogador". Mas na versão 2, você pode implementar o modo multiplayer - e então está enfrentando problemas. Você precisará reescrever e adaptar muito código, porque seu design não suporta instanciar vários players.

O mesmo é com caches. Ou madeireiros. Ou interfaces de rede. Hoje, você acha que precisará apenas de um, sempre, com certeza. Mas em uma versão futura você precisará adicionar um segundo. Esteja ciente desta situação.

Uooo
fonte
1

Existem classes singleton e esse é um padrão de design comum.

Também existem classes que nunca são instanciadas. Se você possui funções que NÃO operam em nenhum estado persistente (por exemplo, elas recebem a entrada e a transformam), geralmente você pode usar um método estático. Em algumas linguagens (como Java), esses métodos estáticos seriam declarados em uma classe, mas a própria classe nunca será instanciada.

Uri
fonte
1

O padrão singleton é comum. Ele permite impor uma instância única da classe.

Mas, para alguns, é muito comum, por isso se torna um antipadrão. A razão para isso é porque é praticamente igual ao estado global. E qualquer estado global é difícil de zombar, testar e depurar. Mas, ao mesmo tempo, ter que passar explicitamente essa instância em qualquer lugar do código pode fazer com que o código fique muito inchado. Mas isso fará você pensar na arquitetura adequada. Se várias classes usarem esse único singleton, você pode pensar que elas estão relacionadas de alguma forma e criar ancestral comum para elas, que encapsularão essa instância para elas.

Eufórico
fonte
1

É ruim supor que algo seja universalmente ruim. No seu caso, talvez seja uma boa ideia, mas, como você está usando uma linguagem que não é OO, é mais apropriado provavelmente usar apenas métodos e variáveis ​​soltas e colocá-los em uma biblioteca comum que você inclui no seu outro trabalho.

jwenting
fonte
1

Você está fazendo duas perguntas em uma.

  1. Não, não há nada ruim em ter uma classe que terá apenas uma instância.
  2. Agrupar variáveis ​​e métodos em uma classe sem uma razão real para isso é um design ruim.
Tulains Córdova
fonte