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