O Service Locator é apenas o menor de dois males, por assim dizer. O "menor" se resumindo a essas quatro diferenças ( pelo menos não consigo pensar em nenhuma outra agora ):
Princípio de Responsabilidade Única
O Service Container não viola o Princípio de Responsabilidade Única, como o Singleton faz. Singletons combinam criação de objetos e lógica de negócios, enquanto o Service Container é estritamente responsável por gerenciar os ciclos de vida de objetos de seu aplicativo. Nesse sentido, o Service Container é melhor.
Acoplamento
Os singletons geralmente são codificados permanentemente em seu aplicativo devido às chamadas de método estático, o que leva a dependências fortemente acopladas e difíceis de simular em seu código. O SL, por outro lado, é apenas uma classe e pode ser injetado. Portanto, embora todas as suas classes dependam disso, pelo menos é uma dependência fracamente acoplada. Portanto, a menos que você implemente o ServiceLocator como um Singleton, isso é um pouco melhor e também mais fácil de testar.
No entanto, todas as classes que usam o ServiceLocator agora dependerão do ServiceLocator, que também é uma forma de acoplamento. Isso pode ser atenuado usando uma interface para o ServiceLocator, de forma que você não esteja vinculado a uma implementação ServiceLocator concreta, mas suas classes dependerão da existência de algum tipo de Locator, ao passo que não usar um ServiceLocator aumenta drasticamente a reutilização.
Dependências ocultas
Porém, o problema de ocultar dependências existe muito. Quando você apenas injeta o localizador em suas classes de consumo, você não conhecerá nenhuma dependência. Mas, em contraste com o Singleton, o SL geralmente instancia todas as dependências necessárias nos bastidores. Então, quando você busca um serviço, você não termina como Misko Hevery no exemplo do CreditCard , por exemplo , você não tem que instanciar todas as dependências das dependências manualmente.
Buscar as dependências de dentro da instância também está violando a Lei de Demeter , que afirma que você não deve pesquisar colaboradores. Uma instância deve falar apenas com seus colaboradores imediatos. Este é um problema com Singleton e ServiceLocator.
Estado Global
O problema do estado global também é um pouco mitigado porque quando você instancia um novo Service Locator entre os testes, todas as instâncias criadas anteriormente são excluídas também (a menos que você cometeu o erro e as salvou em atributos estáticos no SL). Isso não vale para nenhum estado global em classes administradas pelo SL, é claro.
Consulte também Fowler em Service Locator vs Dependency Injection para uma discussão muito mais detalhada.
Uma observação sobre sua atualização e o artigo vinculado por Sebastian Bergmann sobre o código de teste que usa Singletons : Sebastian não sugere, de forma alguma, que a solução alternativa proposta torna o uso de Singleons menos problemático. É apenas uma maneira de tornar o código que de outra forma seria impossível de testar mais testável. Mas ainda é um código problemático. Na verdade, ele observa explicitamente: "Só porque você pode, não significa que você deveria".