我已经编程了一段时间,但从未对理解每个概念的含义感兴趣,我可能会使用各种编程概念,但不知道它。
服务定位器: 对我来说,是指通过减少代码量来加快开发速度的快捷方式记录。一个问题是:可能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)
然后,在理论上(最好用简单的例子),这些概念中的每一个意味着什么?我是正确的,还是有什么不对/可以改进?
谢谢!
答案 0 :(得分:20)
服务位置和依赖注入首先用于解耦类,以便可以轻松地测试和更改它们。
当您将注册和解决部分 IoC容器与服务定位器进行比较时 >似乎是一样的。
您可以将IoC容器用作服务定位器,这被视为反模式。使用服务位置时,您始终必须在整个架构中主动调用服务定位器。所以你要解耦你的课程,但另一方面你将它们全部联系到服务定位器。此外,使用服务定位器进行依赖性发现更加困难,因为您隐藏了依赖项。而使用依赖注入,您可以使用构造函数注入将依赖项设置为“public”。
使用IoC容器时,请使用依赖注入(构造函数注入或属性注入)。现在,IoC容器可以通过查看构造函数参数来重新调整依赖关系图,并创建整个依赖关系图。这称为自动布线。服务定位器无法自动连接依赖项。 正如我已经提到的,你不会被迫使用自动接线,你可以通过简单地直接在每个类中调用IoC容器来轻松地使用像服务定位器这样的IoC容器,但是你不应该!< / p>
另请参阅:https://stackoverflow.com/a/11319026/175399
答案 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功能。