В последнее время я сталкиваюсь с такой проблемой. Service Locator vs Depedency Injection.
Я согласен с Марком в том, что нужно вводить отдельные мелкозернистые объекты в конструктор по мере необходимости. Единственный недостаток, как подчеркнул Марк, состоит в том, что при построении графа сложного объекта вам неизбежно придется начинать где-то . Это означает, что ваши высокоуровневые объекты будут иметь лотов сервисов (объектов), внедренных в них.
Самый простой способ - использовать что-то для выполнения тяжелой работы за вас. Ярким примером этого является Google Guice, который мне кажется очень хорошим способом решения проблем. К сожалению, это написано для Java! Есть версии о PHP; Я не уверен, что кто-то из них вполне соответствует Guice на данный момент.
Я написал пост на эту тему , в котором более подробно; что вы можете найти интересным. Он включает в себя простую реализацию инфраструктуры внедрения зависимостей .
Суть в том, что если у вас есть класс Foo с рядом требований, вы можете создать свой класс следующим образом:
/**
* Depends on db, logger and foomodel.
*/
class Foo
{
private $db;
private $logger;
private $fooModel;
/**
* (other documentation here)
* @inject
*/
public function __construct(IDbService $db, ILoggerService $logger, $iModelService $model)
{
// do something
}
}
Если вам нужен новый объект Foo , вы просто запрашиваете структуру внедрения зависимостей , создающую вам один :
$foo = $serviceInjector->getInstance('Foo');
Инжектор зависимостей выполнит тяжелую работу, убедившись, что он внедряет зависимости. Это включает в себя любые зависимости зависимостей, если это имеет смысл. Другими словами, он рекурсивно рассортирует все по дереву.
Позже, когда вы обнаружите, что вам нужен объект IBarService , вы можете просто добавить его в Construtor, не изменяя никакого другого кода!