Já ouvi inúmeras vezes sobre as armadilhas dos singletons / globais, e entendo por que eles são tão frequentemente desaprovados.
O que não entendo é qual é a alternativa elegante e não bagunçada. Parece que a alternativa ao uso de Singletons / globais sempre envolve a passagem de objetos em um milhão de níveis através dos objetos de seu mecanismo até que eles atinjam os objetos que precisam deles.
Por exemplo, no meu jogo, pré-carrego alguns ativos quando o jogo é iniciado. Esses ativos não são usados até muito mais tarde, quando o jogador navega pelo menu principal e entra no jogo. Devo passar esses dados do meu objeto Game, para o meu objeto ScreenManager (apesar de apenas uma tela realmente se importar com esses dados), para o objeto Screen apropriado e para qualquer outro lugar?
Parece que estou trocando dados de estado global por injeção de dependência desordenada, passando dados para objetos que nem se importam com os dados, exceto com o objetivo de repassá-los a objetos filho.
Este é um caso em que um Singleton seria uma coisa boa ou há alguma solução elegante que me falta?
fonte
Se você não pode / não pode ter uma parte do código que "sabe" magicamente sobre alguns dados, eles precisam ser passados de alguma forma. No entanto, isso não significa que deve necessariamente passar apenas por argumentos.
No seu exemplo de exemplo, você não poderia ter algum tipo de "AssetManager" que carregasse e armazenasse os ativos e, então, o ScreenManager precisaria apenas de uma referência a isso (provavelmente na criação)? Nesse sentido, você está passando as referências aos ativos agrupados em outro objeto e pode passar isso uma vez, na inicialização, em vez de passá-lo para a função folha quando necessário.
Agora, IMHO, que o AssetManager, sendo o tipo de coisa que você só quer, pode muito bem ser um singleton. Desde que você entenda as armadilhas e codifique-as especificamente para evitá-las (suponha que o singleton seja acessado simultaneamente a partir de vários threads e apunhale-se com um garfo sempre que fizer algo que precisa bloquear), e se nocauteie.
fonte
Eu acho que Jason D está absolutamente certo - é assim que eu lidaria com isso:
O jogo possui uma instância do AssetManager, um objeto do qual você pode obter qualquer ativo pelo nome.
No jogo:
No ScreenManager:
Na tela:
Agora todas as telas têm acesso a todos os ativos necessários. Isso não é mais complexo ou louco do que usar globals ou singletons, e você tem a opção de ter duas instâncias do jogo em execução no mesmo aplicativo sem conflitos. Certa vez, tive que criar um jogo composto por 8 minijogos, todos compartilhando as mesmas classes / estruturas básicas. Eu tive que refatorar todos os meus globals / singletons para usar esse estilo de referência e nunca olhei para trás. As únicas coisas que devem ser globais são coisas que só podem existir fisicamente uma vez, como áudio, redes, E / S etc.
fonte
Você pode usar o padrão de fábrica para substituir o Singleton . Em seguida, a classe factory tem o controle sobre quantas instâncias você pode criar, as quais você pode alterar facilmente mais tarde quando achar que precisa de mais de uma
AssetManager
. Conforme declarado neste artigo :Outra possibilidade bastante limitada é tornar a classe estática (o que não acho viável para um AssetManager e apenas possível em linguagens que tenham classes estáticas). Mas isso funciona apenas se você não precisar de herança / polimorfismo. É uma solução muito inflexível:
Trata-se de métodos estáticos, mas também pode ser aplicado a classes estáticas.
fonte