12

我已经编程了一段时间,但从未有兴趣从理论上了解每个概念的含义,我可能正在使用各种编程概念,但并不知道。

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)

那么,理论上(最好有简单的例子),这些概念中的每一个是什么意思?我是正确的,还是有什么问题/可以改进?

谢谢!

4

2 回答 2

20

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

当您将IoC 容器的注册解析部分与服务定位器进行比较时,它似乎是相同的。

您可以将 IoC 容器用作服务定位器,这被​​认为是一种反模式。当您使用服务定位时,您总是必须在整个架构中主动调用服务定位器。因此,您将类解耦,但另一方面,您将它们全部耦合到服务定位器。此外,使用服务定位器发现依赖关系更加困难,因为您隐藏了依赖关系。而使用依赖注入,您可以使用构造函数注入将依赖项“公开”。

当您使用 IoC 容器时,您会使用依赖注入(构造函数注入或属性注入)。IoC 容器现在能够通过查看构造函数参数来解析依赖关系图并创建整个依赖关系图。这称为自动接线。服务定位器无法自动连接依赖项。正如我已经提到的,您不必强制使用自动连接,您可以通过简单地直接在每个类中调用 IoC 容器来轻松使用 IoC 容器,就像服务定位器一样,但您不应该

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

在此处输入图像描述

于 2012-04-07T09:45:59.120 回答
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);

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

一个 DI 容器,自动处理依赖注入。您只需对其进行配置,以便它知道在询问抽象时要返回哪些具体类。容器处理对象创建,通过构造函数和/或属性注入依赖项。根据容器(我不知道 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 容器提供了 IoC 功能。

于 2012-04-07T07:53:27.253 回答