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

Gab*_*tos 12 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();
Run Code Online (Sandbox Code Playgroud)

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

以下是我对它的理解:

$app = new System\Application(System\Config::load());
Run Code Online (Sandbox Code Playgroud)

控制反转:不了解这种设计模式(或者理解但不知道我做的是IoC)

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

谢谢!

Roo*_*ian 20

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

当你比较寄存器决心的部分IoC容器服务定位似乎是相同的.

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

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

另见:https://stackoverflow.com/a/11319026/175399

在此输入图像描述


Mik*_*eSW 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);
Run Code Online (Sandbox Code Playgroud)

通常构造函数将抽象(接口)作为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) {}
  }
Run Code Online (Sandbox Code Playgroud)

DI容器提供IoC功能时,IoC和DiC一起使用.