Temos uma classe que contém informações de configuração do aplicativo. Costumava ser um único. Após alguma revisão arquitetônica, fomos orientados a remover o singleton. Vimos alguns benefícios de não usar o singleton no teste de unidade porque podemos testar diferentes configurações ao mesmo tempo.
Sem o singleton, temos que passar a instância por toda parte em nosso código. Está ficando tão confuso, então escrevemos um invólucro de singleton. Agora que estamos portando o mesmo código para PHP e .NET, gostaria de saber se há um padrão melhor que podemos usar para o objeto de configuração.
fonte
A melhor maneira é usar um padrão de fábrica. Quando você constrói uma nova instância de sua classe (na fábrica), você pode inserir os dados "globais" no objeto recém-construído, seja como uma referência a uma única instância (que você armazena na classe de fábrica) ou copiando os dados relevantes dados no novo objeto.
Todos os seus objetos conterão os dados que costumavam viver no singleton. Não acho que haja muita diferença no geral, mas pode tornar seu código mais fácil de ler.
fonte
Posso estar afirmando o óbvio aqui, mas há uma razão pela qual você não pode usar uma estrutura de injeção de dependência como Spring ou Guice ? (Eu acredito que o Spring também está disponível para .NET agora).
Dessa forma, a estrutura pode conter uma única cópia dos objetos de configuração e seus beans (serviços, DAOs, qualquer que seja) não precisam se preocupar em procurá-los.
Esta é a abordagem que costumo adotar!
fonte
Se você usa Spring Framework , pode apenas criar um bean regular. Por padrão (ou se você definir explicitamente
scope="singleton"
) apenas uma instância do bean é criada e essa instância é retornada toda vez que o bean é usado em uma dependência ou recuperado viagetBean()
.Você obtém a vantagem da instância única, sem o acoplamento do padrão Singleton.
fonte
A alternativa é passar o que você precisa em vez de pedir coisas a um objeto.
fonte
não acumule responsabilidades para um único objeto de configuração, pois ele terminará em um objeto muito grande que é difícil de entender e frágil.
Por exemplo, se você precisar de outro parâmetro para uma classe específica, você altera o
Configuration
objeto e, a seguir, recompila todas as classes que o utilizam. Isso é um tanto problemático.Tente refatorar seu código para evitar um
Configuration
objeto comum, global e grande . Passe apenas os parâmetros necessários para as classes de cliente:deve ser refatorado para:
uma estrutura de injeção de dependência ajudará muito aqui, mas não é estritamente necessária.
fonte
Você pode realizar o mesmo comportamento do singleton usando métodos estáticos. Steve Yegge explica isso muito bem neste post.
fonte
É possível uma classe que contenha apenas métodos e campos estáticos? Não tenho certeza de qual é a sua situação, mas pode valer a pena investigar.
fonte
Depende de quais ferramentas / frameworks etc. estão sendo usados. Com as ferramentas de injeção de dependência / ioc, muitas vezes ainda é possível obter desempenho / otimizações singleton fazendo com que o contêiner di / ioc use o comportamento singleton para a classe necessária - (como uma interface IConfigSettings) criando apenas uma instância da classe. Isso ainda pode ser substituído por teste
Como alternativa, pode-se usar uma fábrica para criar a classe e retornar a mesma instância cada vez que você solicitá-la - mas, para testar, pode retornar uma versão fragmentada / simulada
fonte
Reveja a possibilidade de fazer configuração como interface de retorno de chamada. Portanto, seu código sensível à configuração ficará:
O código de inicialização do sistema parecerá:
fonte
Você poderia usar uma estrutura de injeção de dependência para aliviar a dor de passar no objeto de configuração. Um decente é o ninject, que tem a vantagem de usar código em vez de xml.
fonte
Talvez não seja muito limpo também, mas você poderia passar os bits de informação que deseja alterar para o método que cria o singleton - em vez de usar
você pode chamar
createSingleton(Information info)
diretamente na inicialização do aplicativo (e nos métodos de configuração dos testes de unidade).fonte
Singletons não são maus, mas o padrão de design é defeituoso. Eu tenho uma classe que desejo apenas criar uma única instância durante o tempo de execução, mas quero criar várias instâncias isoladas durante o teste de unidade para garantir resultados determinísticos.
DI usando Spring, etc, é uma opção muito boa, mas não a única opção.
fonte