这是构建器注入的一个合理的实现吗? [英] Is this a sane implementation of constructor injection?
问题描述
以下是从我的服务定位器问题,我决定使用代替注入构造函数。请考虑以下代码:
Following on from my question on service locators I have decided to use constructor injection instead. Please consider the following code:
<?php
interface IAppServiceRegistry {
public function getDb();
public function getLogger();
}
interface IFooServiceRegistry extends IAppServiceRegistry {
public function getFooBarBazModel();
}
class AppServiceRegistry
implements IAppServiceRegistry, IFooServiceRegistry
{
private $logger;
private $db;
private $fooBarBazModel;
public function getDb() {
// return db (instantiate if first call)
}
public function getLogger() {
// return logger (instantiate if first call)
}
public function getFooBarBazModel() {
if (!isset($this->fooBarBazModel)) {
$this->fooBarBazModel = new FooBarBazModel( $this->getDb() );
}
return $this->fooBarBazModel;
}
}
// Example client classes:
/**
* Depends on db, logger and foomodel.
*/
class Foo {
private $db;
private $logger;
private $fooModel;
public function __construct(IFooServiceRegistry $services) {
$this->db = $services->getDb();
$this->logger = $services->getLogger();
$this->fooModel = $services->getFooModel();
}
}
/**
* Depends on only db and logger.
*/
class BarBaz {
private $db;
private $logger;
public function __construct(IAppServiceRegistry $services) {
$this->db = $services->getDb();
$this->logger = $services->getLogger();
}
}
然后我会向注册表添加新的服务工厂方法随着应用程序的发展,在逻辑上适当地创建了隔离接口。
Then I would add new service factory methods to the registry as the application evolved, creating segregated interfaces wherever logically appropriate.
这个方法是否合理?
推荐答案
虽然我通常不读php,我觉得我理解的很多。在技术上,它看起来不错,但是你写的是
Although I don't normally read php, I think I understand most of it. Technically, it looks fine, but then you write
随着应用程序的发展,我将向注册表添加新的服务工厂方法
I would add new service factory methods to the registry as the application evolved
这往往会损害松耦合的想法,因为您现在有一个专门的服务定位器,而不是通用服务定位器。
That tends to hurt the idea of loose coupling because instead of a general-purpose Service Locator you now have a specialized Service Locator.
将这样一个服务注册表注入到每个类中,针对单一责任原则(SRP)因为一旦一个类有权访问注册表,它比原来构想的要求要容易得多,所以你最终会得到一个 God Object 。
Injecting such a serivce registry into each class works against the Single Responsibility Principle (SRP) because once a class has access to the registry, it is too easy to request yet another dependency than originally conceived, and you will end up with a God Object.
最好将所需的依赖项直接注入到需要的类中他们。因此,您的Foo类的构造函数应该使用数据库,记录器和fooModel,而BarBaz类应该只能使用db和logger参数。
It would be better to inject the required dependencies directly into the classes that need them. Thus, your Foo class' constructor should take a db, a logger and a fooModel, while the BarBaz class should take only a db and a logger parameter.
下一个问题可能是:如果我需要很多不同的依赖来执行工作怎么办?这将需要一个真正难看的构造函数,具有很多参数,这与其他着名的OO实践相反。
The next question may then be: What if I need a lot of different dependencies to perform the work? That would require a truly ugly constructor with lots of parameters, and this goes against other well-known OO practices.
如果你需要很多依赖项,可能违反SRP,并且应该尝试将您的设计分解成更细粒度的对象:)
True, but if you need lots of dependencies, you are probably violating the SRP and should try to split your design into finer-grained objects :)
这篇关于这是构建器注入的一个合理的实现吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!