Сервисный локатор, так сказать, меньшее из двух зол.«Меньше» сводится к этим четырем различиям ( по крайней мере, я не могу думать ни о каких других сейчас ):
Принцип единой ответственности
Контейнер услуг ненарушать принцип единой ответственности, как синглтон.Singletons смешивает создание объектов и бизнес-логику, в то время как Service Container строго отвечает за управление жизненными циклами объектов вашего приложения.В этом отношении Service Container лучше.
Связь
Синглтоны обычно жестко запрограммированы в вашем приложении из-за статических вызовов методов, что приводит к сильной связи и труднодоступным зависимостям в вашем коде.SL с другой стороны - это всего лишь один класс, и его можно вводить.Так что, хотя все ваши классы будут зависеть от этого, по крайней мере, это слабо связанная зависимость.Поэтому, если вы не внедрили ServiceLocator как сам Singleton, это несколько лучше, а также проще для тестирования.
Однако все классы, использующие ServiceLocator, теперь будут зависеть от ServiceLocator, который также является формой соединения.Этого можно избежать, используя интерфейс для ServiceLocator, чтобы вы не были связаны с конкретной реализацией ServiceLocator, но ваши классы будут зависеть от существования какого-либо типа Locator, тогда как отсутствие использования ServiceLocator вообще увеличивает повторное использование.
Скрытые зависимости
Однако проблема сокрытия зависимостей существует в значительной степени.Когда вы просто внедряете локатор в ваши потребляющие классы, вы не будете знать никаких зависимостей.Но в отличие от Singleton, SL обычно создает все зависимости, необходимые за кулисами.Поэтому, когда вы получаете Службу, вы не видите, как Misko Hevery в примере CreditCard , например, вам не нужно создавать экземпляры всех зависимостей вручную.
Извлекать зависимости извнутри экземпляра также нарушается Закон Деметры , который гласит, что вы не должны копаться в соавторах.Экземпляр должен общаться только со своими непосредственными сотрудниками.Это проблема как для Singleton, так и для ServiceLocator.
Global State
Проблема Global State также несколько смягчается, поскольку при создании экземпляра нового Service Locator между тестами удаляются все ранее созданные экземпляры.также (если вы не допустили ошибку и не сохранили их в статических атрибутах в SL).Конечно, это не относится к любому глобальному состоянию в классах, управляемых SL.
Также см. Фаулера в Локатор службы и Внедрение зависимостей для более углубленного обсуждения.
Примечание о вашем обновлении и связанная статья Себастьяна Бергмана о тестировании кода, использующего Singletons : Себастьян никоим образом не предполагает, что предложенный обходной путь делает использование Singleons менеепроблема.Это всего лишь один из способов сделать код, который в противном случае было бы невозможно проверить более тестируемым.Но это все еще проблемный код.На самом деле он прямо отмечает: «Только то, что ты можешь, не значит, что ты должен».