这是依赖注入吗?这是一种不好的做法吗?

2024-05-15

我有一个小框架,我是这样编码的。我不确定这是否称为依赖注入。我不知道它是否像设计模式。我也不知道并且想知道是否通过$this因为 param 是一种不好的做法。

看看这个; (不是一个有效的示例,只是将这些代码写入浏览器中以供解释。)

/* This is engine model */
require_once('Database.class.php');
require_once('Image.class.php');
require_once('Misc.class.php');
require_once('BBCode.class.php');

class FrameWork_Engine_Model
{
    public $database, $config, $misc, $bbcode, $controller, $image;

    function __construct($config)
    {
            $this->database = new Database($configParams);
            $this->image = new Image($this);
            $this->misc = new Misc($this);
            $this->bbcode = new BBCode($this);
            $this->controller = new Controller($this); //here I call Register controller depending on routing, in this case, register controller.
    }
 ...
 }

 /* This is register controller */
 class Register extends Base_Controller
 {
       /*I can access anything over Engine Model in my controllers */
       $this->engine->database->query(); //I access database model
       $this->engine->bbcode->tag('you'); //I access bbcode model
       $this->engine->image->sanitizeUploadedFile(); //I access image model

       //etc. I can access others models like this.
 }

基本上,我的控制器可以通过引擎模型访问任何模型。我相信dependency injection is all about injecting dependencies into controllers?就像,我的注册控制器需要数据库模型、路由模型和模板模型才能工作。这里拥有它所依赖的一切。我错了吗?

话虽如此,我的问题是:

  1. 这是一个有效的依赖注入示例吗?如果不是,那是什么?它在设计模式中有名称吗?

  2. 如果与依赖注入无关,需要做哪些改变才能是DI?

  3. 正在路过$this新创建的类上的参数是一种不好的做法吗?如果是这样,为什么?

诗。我知道 stackoverflow 不喜欢在一个主题中问 3 个问题,但我不想复制粘贴整个文本来问他们。


你快到了。

问题1

不,我不认为它是一个有效的依赖注入示例。它有点类似于服务定位器(因为您将整个容器注入到您的服务中并使用它来“定位”依赖服务)。

问题2

您在依赖项注入和依赖项注入容器之间造成了一些混淆。

首先,依赖注入意味着在运行时将依赖项推送到对象中,而不是创建/拉取它们。

举个例子:

//hardcoded dependecies
class BadService
{
    public function __construct() 
    {
        $this->dep1 = new ConcreteObject1();
        $this->dep2 = new ConcreteObject2();
    }
}

所以在上面的例子中,BadService使得无法在运行时连接其他依赖项,因为它们已经被硬拉到构造函数本身中。

//service locator pattern
class AlmostGoodService
{
    public function __construct(Container $container)
    {
        $this->dep1 = $container->getADep1();
        $this->dep2 = $container->getADep2();
    }
}

In the AlmostGoodService例如,我们已经从前面的示例中删除了硬依赖项,但我们仍然依赖于容器的特定实现(这意味着如果不提供该容器的实现,我们的服务就无法重用)。这是与您正在做的事情相匹配的示例。

//dependecy injection    
class GoodService
{
    public function __construct($dep1, OptionalInterface $dep2)
    {
        $this->dep1 = $dep1;
        $this->dep2 = $dep2;
    }
}

The GoodService服务不关心其具体依赖项的创建,并且可以在运行时轻松地与实现服务“协议”的任何依赖项“连接”$dep1或可选接口$dep2(因此名称为控制反转 http://en.wikipedia.org/wiki/Inversion_of_control- 依赖注入背后的基本概念)。

进行这种接线的组件称为依赖注入容器 http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container.

Now, a 依赖注入容器 http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container最简单的形式只不过是一个能够在运行时根据某种形式的配置连接对象的对象。

我说你已经差不多了,但是你的实现存在一些问题:

  • 接线应该是惰性的(您不想让所有这些在您的构造函数中工作,因为您的应用程序随着它的增长会大大减慢)
  • 你不应该传递整个容器($this)作为依赖项,因为这样你就会回退到较弱的控制反转 http://en.wikipedia.org/wiki/Inversion_of_control,即一个服务定位器 http://en.wikipedia.org/wiki/Service_locator_pattern。您应该将具体的依赖项传递给您的服务构造函数

问题3

在某些情况下,您会发现自己想要通过整个考试$container作为对服务(即控制器或惰性服务工厂)的依赖,但通常最好远离这种做法,因为它将使您的服务更可重用且更易于测试。当您感觉您的服务有太多依赖项时,这是一个好兆头,表明您的服务做了太多事情,现在是拆分它的好时机。

原型容器实现

因此,根据我上面的回答,这是一个修改后的(远非完美)实现:

/* This is the revised engine model */
class FrameWork_Engine_Model
{
    function __construct($config)
    {
            $this->config = $cofig; 
    }

    public function database()
    {
        require_once('Database.class.php');
        return new Database($this->config['configParams']);
    }

    public function bbcode()
    {
        require_once('BBCode.class.php');
        return new BBCode($this->database());
    }

    public function image()
    {
        require_once('Image.class.php');
        $this->image = new Image($this->config['extensionName']);
    }
    ....

    public function register_controller($shared = true)
    {
        if ($shared && $this->register_controller) {
          return $this->register_controller;
        }

        return $this->register_controller = new Register_Controller($this->database(), $thus->image(), $this->bbcode());
    }
 }

现在,要使用您的服务:

$container = new FrameWork_Engine_Model(); 
$container->register_controller()->doSomeAction()

有什么可以改进的地方?您的容器应该:

  • 提供一种共享服务的方式 - 即仅初始化一次
  • be lockable https://github.com/catacgc/juice-di-container#locking-behaviour- 提供配置后锁定的方法
  • 能够与其他容器“合并” - 这样您的应用程序将真正模块化
  • allow 可选的依赖项 http://symfony.com/doc/2.1/book/service_container.html#making-references-optional
  • allow scopes http://symfony.com/doc/2.0/cookbook/service_container/scopes.html
  • support 标签服务 http://symfony.com/doc/2.1/book/service_container.html#tags

准备使用 DI 容器实现

所有这些都附有关于依赖注入 http://en.wikipedia.org/wiki/Dependency_injection

  • Pimple http://pimple.sensiolabs.org/- PHP 5.3 轻量级 DI 容器
  • Symfony2 DI 容器 http://symfony.com/doc/master/components/dependency_injection/introduction.html- PHP 5.3 具有完整的 DI 容器功能
  • Juice DI https://github.com/catacgc/juice-di-container- 小型 PHP 5.2 DI 容器
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这是依赖注入吗?这是一种不好的做法吗? 的相关文章

随机推荐

  • 用作 ServiceStack 的 IoC 时在 autofac 中配置生命周期范围

    我目前正在使用 AutoFac 作为我们的 ServiceStack Web 服务应用程序的 DI 容器 我能够配置接线和所有内容 但在阅读了有关范围的部分后 我不知道在注册我的组件时最好使用哪个范围 在我们的特定情况下 我认为 PerHt
  • 如何在禁用的 HTML 按钮上呈现工具提示

    我有一个 HTML 按钮 我尝试根据按钮的 标题 属性在其上渲染工具提示 但它没有渲染 主要是因为它被禁用了 然后 我尝试将按钮包装在跨度中并设置跨度的 标题 属性 将鼠标悬停在包含在跨度中的按钮上仍然没有效果 工具提示将呈现在不属于按钮标
  • 如何从 iOS 应用程序检测不安全的 wifi 网络

    我想检测我的应用程序中是否存在不安全的 wifi 网络 是否有任何公共 iOS API 可以实现相同的目的 没有记录的 API 可以获取该信息 如果您的应用程序需要通过网络发送和接收敏感数据 您通常应该假设没有安全连接
  • 属性中的角度表达式

    我有一个使用 Angular 的页面 其中我从引导程序实现了弹出窗口 img class state msg 数据内容无法正确呈现 它按字面意思返回 item status message 而不是 message 的值 角度在 数据 属性中
  • Jquery POST 获取建议列表

    我有下一个代码 它运行良好 问题是当用户写完单词时 脚本不断创建后调用并不断更改建议列表 我想做一些事情 如果用户继续写一个单词 脚本会停止所有的 post 调用 只执行最后一个 inputString keydown function l
  • 用数字 1-1000 填充 Postgres 数据库?

    我是 pgAdmin3 的新手 我想用数字 1 1000 填充 pgAdmin3 中的数据库 我该怎么做呢 目前 我创建了一个名为 MyDatabase 的数据库 其中没有任何内容 每行应与其数值相对应 第 1 行应包含 1 第 2 行应包
  • JSF 中基于两个组件的组合的验证/转换

    我正在开发一个 JSF Web 应用程序 我需要使用周期性作为数据结构 以下是我使用的 Java 类 public class Periodicity implements Serializable private Integer valu
  • MySQL 帮助:如何查找客户的所有订单,直到价格 <= 20 且状态='未付款'

    我认为通过提供以下示例可以更好地理解我的问题 我有一个包含以下数据的表 orderid Price username paymentstatus 1 10 john unpaid 2 10 john unpaid 4 10 john unp
  • 如何在安装过程中运行“.bat”文件?

    在安装项目中 诸如 exe dll js vbs 之类的可执行文件是可以接受的 但无法运行 bat自定义操作中的文件 问题是如何运行 bat安装过程中的文件 好吧 经过大量搜索和反复试验 我解决了这个问题 我不确定这是否是最好的方法 但它确
  • ORACLE:未找到数据——但数据存在

    调试包过程 当实际上有数据时却找不到数据 仅测试 SELECT SELECT trim trailing from GL SECURITY as DUMMY FROM b2k user b2k WHERE sms username FUCH
  • 面向服务的架构 - AMQP 或 HTTP

    一点背景 非常大的整体 Django 应用程序 所有组件都使用相同的数据库 我们需要分离服务 以便我们可以独立升级系统的某些部分而不影响其余部分 我们使用 RabbitMQ 作为 Celery 的代理 现在我们有两个选择 使用 REST 接
  • 在 Yesod 生态系统中,对某些文本进行 urlencode 的最佳方式是什么?

    我想对一些文本进行 url 编码 例如 用 20 替换每个空格等 我找到了 HTTP Network HTTP Base urlEncode 并且可以使用它 但我想知道是否还有其他通常在 Yesod 生态系统中使用的东西 不幸的是 由于 U
  • 为什么在方法中声明的对象在方法返回之前会受到垃圾回收?

    考虑在方法中声明的对象 public void foo final Object obj new Object A long run job that consumes tons of memory and triggers garbage
  • $(this) 在 jQuery 中如何工作

    jQuery 标签是如何实现的 this 到底工作吗 我知道如何使用它 但是 jQuery 如何知道哪个元素是 活动的 用于获取当前项目的原始 Javascript 标签是什么 还是只是 jQuery The this是一个简单的 java
  • 如何在Union中查询不同类型的同一字段?

    我有以下型号 type Duck category Baz type Foo size FooSize type Bar size BarSize union Baz Foo Bar 以下查询会引发错误Validation error of
  • React this.state 未定义?

    我正在遵循 Pluralsight 的初学者教程 在表单提交时将值传递给addUser组件方法 我需要将 userName 推送到this state users但我收到错误 App jsx 14 Uncaught TypeError Ca
  • 部署在github中的Jekyll显示index.html文件的原始文本

    我正在尝试使用来自的分叉存储库来部署 Jekyll 网站https github com cotes2020 jekyll theme chirpy https github com cotes2020 jekyll theme chirp
  • Selenium WebDriver - 意外的模式对话框警报

    我正在尝试使用 WebDriver 来自动化网站 我正在使用 Firefox 驱动程序 但主页有一个弹出模式警报窗口 显示 您需要使用 IE 6 0 才能查看此应用程序 还有一些 功能可能无法使用 我检查了页面的来源 它有一个功能 Moda
  • 客户端登录 - 如何在客户端安全地存储凭据?

    许多 API 都提供通过用户 密码组合远程访问其数据的功能 我想知道存储这些值的最佳方式是什么 高度安全的方式 即使 100 是不可能的 以便直接连接它们而无需每次都询问这些值 我推荐以下三种方法之一 使用身份验证令牌完全避免存储密码 在此
  • 这是依赖注入吗?这是一种不好的做法吗?

    我有一个小框架 我是这样编码的 我不确定这是否称为依赖注入 我不知道它是否像设计模式 我也不知道并且想知道是否通过 this因为 param 是一种不好的做法 看看这个 不是一个有效的示例 只是将这些代码写入浏览器中以供解释 This is