服务定位器,依赖注入(和容器)和控制反转

时间:2012-04-06 22:25:58

标签: php design-patterns dependency-injection inversion-of-control service-locator

我已经编程了一段时间,但从未对理解每个概念的含义感兴趣,我可能会使用各种编程概念,但不知道它。

服务定位器: 对我来说,是指通过减少代码量来加快开发速度的快捷方式记录。一个问题是:可能Locator只引用名称空间/类,或者我可以有变量注册表吗?

以下是我对它的理解:

$locator = new ServiceLocator()
$locator->set('app', new System\Application());
$locator->set('db', new System\Pdo());

// Get the objects
$locator->get('db')->connect();
$locator->get('app')->run();

依赖注入(和依赖注入容器): 在对象中注入对象,无论工厂模式如何,都可以更快地访问这些对象。和DI容器?

以下是我对它的理解:

$app = new System\Application(System\Config::load());

控制倒置: 不明白这个设计模式(或者理解,但不知道我做的是IoC)

然后,在理论上(最好用简单的例子),这些概念中的每一个意味着什么?我是正确的,还是有什么不对/可以改进?

谢谢!

2 个答案:

答案 0 :(得分:20)

服务位置和依赖注入首先用于解耦类,以便可以轻松地测试和更改它们。

当您将注册解决部分 IoC容器服务定位器进行比较时 >似乎是一样的。

您可以将IoC容器用作服务定位器,这被​​视为反模式。使用服务位置时,您始终必须在整个架构中主动调用服务定位器。所以你要解耦你的课程,但另一方面你将它们全部联系到服务定位器。此外,使用服务定位器进行依赖性发现更加困难,因为您隐藏了依赖项。而使用依赖注入,您可以使用构造函数注入将依赖项设置为“public”。

使用IoC容器时,请使用依赖注入(构造函数注入或属性注入)。现在,IoC容器可以通过查看构造函数参数来重新调整依赖关系图,并创建整个依赖关系图。这称为自动布线。服务定位器无法自动连接依赖项。 正如我已经提到的,你不会被迫使用自动接线,你可以通过简单地直接在每个类中调用IoC容器来轻松地使用像服务定位器这样的IoC容器,但是你不应该!< / p>

另请参阅:https://stackoverflow.com/a/11319026/175399

enter image description here

答案 1 :(得分:10)

我认为您正确理解了服务定位器。

关于依赖注入,意味着如果一个对象具有构造函数和/或属性依赖关系,那么它们将被外部注入到对象中,而不是自己获取依赖关系的对象

public class MyClass
{
   private $_dep;
   public function __construct($dep=null)
   {
       //$dep has to be injected
       $this->_dep=$dep;                           
   }

   //this is wrong because it couples MyClass to a specific Dependency implementation
   public function __construct()
   {
       $this->_dep=new Dependency();
    }
}
   $dep=new Dependency();
   $obj=new MyClass($dep);

通常构造函数将抽象(接口)作为param,并在类外部实例化一个具体的实现,然后在创建MyClass的新实例时将其传递给构造函数。

DI容器,自动处理依赖注入。您只需配置它,以便它知道在提出抽象时要返回的具体类。 Container处理对象创建,通过构造函数和/或属性注入依赖项。根据容器(我不知道php的一个例子,我只熟悉.net DI容器)你可能还需要注册可以创建的对象类型 它

控制反转意味着取决于较低级别类(依赖性)实现而不是更高级别的类,控制是反转的,因此较低级别的类实现取决于较高级别所需的抽象等级。

//abstraction defined for the use of higher level class
public interface  IRepository {}

// that's the dependency, the lower level class  
public class XmlRepository implements IRepository {}

//the higher level class
 public class MyClass
 {
     public function __construct(IRepository $repo) {}
  }

IoC和DiC一起使用,因为DI Container提供了IoC功能。