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.
Global é ruim porque:
- uma. Causa conflito no namespace
- b. Expõe o estado de forma injustificada
Quando se trata de Singletons
- uma. A maneira explícita de OO de chamá-los impede os conflitos, então aponte a. não é um problema
- b. Singletons sem estado são (como fábricas) não são um problema. Singletons com estado podem novamente cair em duas categorias, aquelas que são imutáveis ou gravam uma vez e leem muitas (arquivos de configuração / propriedade). Estes não são ruins. Singletons mutáveis, que são o tipo de referência, são os que você está falando.
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:
- estabelecemos as regras primeiro para que todos estejam na mesma página
- todos recebem um começo igual no início do jogo
- apenas um conjunto de regras é apresentado para evitar confusão
- as regras não podem mudar ao longo do jogo
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.