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

Php 服务定位器、依赖注入(和容器)和控制反转,php,design-patterns,dependency-injection,inversion-of-control,service-locator,Php,Design Patterns,Dependency Injection,Inversion Of Control,Service Locator,我编程已经有一段时间了,但从来没有对理论上了解每个概念的含义感兴趣,我可能会使用各种编程概念,但并不知道 服务定位器: 对我来说,是指通过减少代码量来加速开发的快捷方式记录。一个问题是:定位器可以只引用名称空间/类,或者我可以有一个变量注册表 以下是我对它的理解: $locator=newServiceLocator() $locator->set('app',new System\Application()); $locator->set('db',新系统\Pdo()); //获取对象 $lo

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

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

以下是我对它的理解:

$locator=newServiceLocator()
$locator->set('app',new System\Application());
$locator->set('db',新系统\Pdo());
//获取对象
$locator->get('db')->connect();
$locator->get('app')->run();
依赖项注入(和依赖项注入容器): 在对象中注入对象,无论工厂模式如何,都可以更快地访问这些对象。和DI容器

以下是我对它的理解:

$app=new System\Application(System\Config::load());
控制反转: 不理解这种设计模式(或者理解但不知道我所做的是否是IoC)

那么,在理论上(最好用简单的例子),这些概念都意味着什么?我是对的,还是错在哪里/可以改进


谢谢

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

关于依赖项注入,意味着如果对象具有构造函数和/或属性依赖项,则这些依赖项由外部注入到对象中,而不是由对象自身获取依赖项

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) {}
  }

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

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

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

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

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

另见:


不确定“更快的访问”是什么意思。全局变量或单例也一样快。我想你说的更多的是模块化。当我有一个DI时,整个类被注入到另一个类中,所以,我不需要另一个设计模式,因为我在我的第二个类中有我所需要的一切。(明白吗?!)等一下。。谁在问这些问题PI将你的评论解释为一个问题。(巴西初学者的事)。你在说什么模块化?如果DI、IoC和服务定位器与此相关,您能再解释一下吗?将注入看作是松耦合的一种形式。不同的模块不必“知道”如何相互访问,但可以插入引用。这使得在不破坏您忘记的东西的情况下更改不同的模块变得非常容易。它不是一种方便的访问方式,而是一种模块化的方法,以实现可持续的代码。很好的解释。所以,DI谈论注入一个对象并将其存储在您注入的类中,以允许将来访问?关于IoC,我不太理解,如果您能解释更多,我感谢您。关于DI,是的。关于IoC,我不知道如何更好地解释它,但是每次一个类指定它需要一个抽象作为依赖项,这就是IoC模式。我对IoC一点也不了解。您可以发布一些示例吗?@GabrielSantos我只能发布.NET的示例。谢谢@Rookian,但不理解.NET=PTo。老实说,我也有类似的问题-我得到了服务定位器(反模式),我想我理解DI,但从我的角度来看,IoC要么是DI,要么是服务定位器-这取决于它的使用方式。从我的观点来看,它是由可能的实现组成的IoC组:服务定位器或DI。。。虽然我是一名PHP开发人员,但我做了一点.NET(C#),我想我可以