php – 使用DI容器替换全局$注册表对象是否可行?

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了php – 使用DI容器替换全局$注册表对象是否可行?脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经开始重构一个小的应用程序来使用一个小的DI容器,而不是拥有
$注册表中:getstuff();在我的课上打电话给我注入一个容器.

这提出了2个问题,

Q1->我扩展了@L_419_0@,并创建一个容器,具有特定于需要DI的每个对象的依赖关系.然后,我提供对象the whole shebang,并在构造函数中对其进行分解,将对象的对象分配给正在构建的对象的类属性.

应该在新的object()调用中分离对象吗?我刚刚发现这样更容易,但是看到我现在是一个男子团体,我只想确认我有正确的方法.

Q2→>我发现如果我在几个主要类上执行此操作,我将遍历的$注册表对象将不会被使用,这是使用DI的正常结果,没有更多的注册表?我可能在容器中注入一个或两个单例,但是它看起来像我所需要的一样,甚至可以很容易地消除它们,因为DI有一个返回相同的对象实例的share()属性,有效地消除了需要单身人士这是摆脱需要注册表/单身人士的应用程序的方式,因为如果这样很容易这样.

Q2:
如果你传递你的$注册表对象….所以你的注册表并不是所谓的注册表(正如福勒描述的).

注册表或多或少是具有get / set方法的全局对象(“众所周知的”).
PHP中,两个用于实现注册表的常见原型是

作为单身人士

class RegistryAsSingleton
{
    public static function getInstance (){
       //the singleton part
    }

    public function getStuff ()
    {
       //some stuff accessed thanks to the registry
    }
}

用静态方法遍布各地

class RegistryAsStatic
{
    public static function getStuff()
    {
    }
}

注册表传递到整个地方使得它只是一个对象:一个容器,而不是提供对其他对象的引用的目的.

您的DI容器(使用Pimple,如您在OP中建议的)是一种注册表本身:它是众所周知的,使您能够从任何地方获取组件.

所以是的,我们可以说您的DI容器将通过执行相同的功能删除注册表的要求和必要性.

但是(总是有一个但是)

如果您正在使用DI Container替换注册表,这可能是错误的.

例如:

//PRobably a Wrong usage of Registry
class NeedsRegistry
{
    public function asAParameter(Registry $pRegistry)
    {
       //Wrong dePEndency on registry where dependency is on Connection
       $ct = $pRegistry->getConnection();
    }

    public function asDirectAccess ()
    {
       //same mistake,more obvIoUs as we can't use another component
       $ct = Registry::getInstance()->getConnection();
    }
}

//probably a wrong replacement for Registry using DI Container
class NeedsContainer
{
    public function asAParameter(Container $pRegistry)
    {
       //We are dependent to the container wITh no needs,//this code should be dependent on Connection
       $ct = $pContainer->getConnection();
    }

    public function asDirectAccess ()
    {
       //should not be dependent on container
       $ct = Container::getInstance()->getConnection();
    }
}

为什么这样坏?因为你的代码比以前更少的依赖,它仍然依赖于一个组件(一个注册表或一个容器),它没有提供一个明确的目标(我们可能会想到这里的接口)

注册表模式在某些情况下是有用的,因为它是一种简单且相当便宜的方法来定义组件或数据(例如全局配置).

通过删除依赖关系来重构上述示例而不依赖于DI的方式将是:

class WasNeedingARegistry
{
    public function asAParameter (Connection $pConnection)
    {
       $pConnection->DOStuff();//The real dependency here,we don't care for 
       //a global registry
    }
}

//the client code would be like
$wasNeedingARegistry = new WasNeedingARegistry();
$wasNeedingARegistry->setConnection($connection);

当然,如果客户端代码知道连接,这可能是不可能的,这可能是您可能首先使用注册表结束的原因.

现在DI发挥作用

使用DI使我们的生活更美好,因为它将处理依赖关系,并使我们能够在即时使用状态下访问依赖关系.

代码中的某个地方,您将配置您的组件:

$container['connection'] = function ($container) {
    return new Connection('configuration');
};
$container['neededARegistry'] = function ($container) {
    $neededARegistry = new NeededARegistry();
    $neededARegistry->setConnection($container['connection']);
    return $neededARegistry;
};

现在你拥有重构代码所需的一切:

// probably a better design pattern for using a Registry 
class NeededARegistry
{
    public function setConnection(Connection $pConnection)
    {
       $this->connection = $pConnection;
       return $this;
    }

    public function prevIoUslyAsDirectAccess ()
    {
       $this->connection->doStuff();
    }
}

//and the client code just needs to kNow about the DI container
$container['neededARegistry']->prevIoUslyAsDirectAccess();

“客户端”代码应尽可能隔离.客户端应该负责并注入自己的依赖项(通过设置方法).客户端不应负责处理其依赖关系.

class WrongClientCode
{
    private $connection;
    public function setConnection(Connection $pConnection)
    {
       $this->connection = $pConnection;
    }

    public function callService ()
    {
       //for the demo we use a factory here
       ServiceFactory::create('Someid')
                       ->setConnection($this->connection)
                       ->call();
       //here,connection was propagated on the solely 
       // purpose of being passed to the Service
    }
}

class GoodClientCode
{
    private $service;
    public function setService(Service $pService)
    {
       //the only dependency is on Service,no more connection
       $this->service = $pService;
    }

    public function callService ()
    {
       $this->service->setConnection($this->connection)
                     ->call();
    }
}

DI容器将配置已经使用其连接正确配置的服务的GoodClientCode

对于Singleton方面,是的,它将使你摆脱它们.希望这可以帮助

脚本宝典总结

以上是脚本宝典为你收集整理的php – 使用DI容器替换全局$注册表对象是否可行?全部内容,希望文章能够帮你解决php – 使用DI容器替换全局$注册表对象是否可行?所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。