依赖注射在现实生活中 [英] Dependency-injection in real life

查看:155
本文介绍了依赖注射在现实生活中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个非常小的MVC框架来增加我的PHP知识和挑战自己。我来到了Classes开始依赖彼此工作的地步。
依赖注入似乎是解决方案这个由大框架使用。



我在Github上发现了 Bucket 并弄乱了一段时间来了解基础知识。 我不能让我的头脑是适合创建一个容器?<​​/ strong>



制作一个大容器,包括每个可能的类可能需要 似乎没有什么对我有反作用,我无法想象这是很好的做法。至少这个表现似乎是糟糕的食谱。



在替代方案中,哪个是制作多个容器,我仍然不知道这个有恶臭的单身人士不需要了。



让我们说下列代码:

  $ session_container = new bucket_Container(); 
$ session_container-> create('Database');
$ session_container-> create('Database_Sessions');

$ log_container = new bucket_Container();
$ log_container-> create('Database');
$ log_container-> create('Database_Log');

所以这里我们有两个容器,或者在这种情况下,完全不同的用法是相互依赖于数据库类。



我的逻辑告诉我上面的代码将创建两个独立的数据库实例 -class,这意味着我仍然需要使数据库 -class单一,以确保并发实例的数据库连接不发生?



这是否正确?

解决方案

我不太了解具体的lib,但假设你可以使用工厂,让工厂返回相同的实例。



编辑:好的,这只是在Bucket GitHub索引页面上。

  class MyFactory { 
函数new_PDO($ container){
返回新的PDO(mysql:host = localhost; dbname = addressbook,root,secret);
}
}

$ bucket = new bucket_Container(new MyFactory());
$ db = $ bucket-> get('pdo');

所以在你的情况下,你可以简单地做:

  class MyFactory {
private $ pdo;
function new_Database($ container){
if($ this-> pdo){
return $ this-> pdo;
}
return $ this-> pdo = new PDO(mysql:host = localhost; dbname = addressbook,root,secret);
}
}
$ factory = new MyFactory();

$ session_container = new bucket_Container($ factory);
$ session_container-> create('Database_Sessions');

$ log_container = new bucket_Container($ factory);
$ log_container-> create('Database_Log');

这样的东西。似乎不像火箭科学。



编辑2:我没有足够的代表点来评论这个问题(有点傻),但是为了回应你的模块化 关心:把容器看成你的应用程序的胶水。实际上,如果你有一个很大的应用程序,你可能只需要在你的应用程序的一个独立部分中粘贴。这是一个有效的封装问题。但即使如此,您仍然需要一个处理最高抽象级别的注入的容器。如果您只是为应用程序的每个部分创建一个单独的容器,那么最终会出现不必要的实例重复,或者您必须应用另一个级别的实例管理,这不会以任何方式改进封装:您仍然在应用程序的不同部分之间共享实例。



我的建议是在引导级使用单个容器。如果您想为应用程序(模块,插件,任何)的特定部分添加封装,请使用子容器。子容器从父容器继承实例,但是父容器对该小孩没有任何意义(就他而言,他还是个学士学位))。可能是Bucket支持这个默认情况下,我知道其他DI容器。如果没有,使用Decorator实现很容易。想象一下这样的东西:

  class MyContainerType extends bucket_Container {

private $ _parent;
private $ _subject;

public function __construct($ factory = null,bucket_Container $ parent = null){
$ this-> _parent = $ parent;
$ this-> _subject = new bucket_Container($ factory);
}

public function get($ key){
$ value = $ this-> _subject-> get($ key);
if($ value){
return $ value;
}
return $ this-> _parent-> get($ key);
}
/ **
*覆盖和授权所有其他方法
* /
}


I am building a really minimal MVC framework to increase my PHP knowledge and challenge myself. I've come to the point where Classes begin to be dependent on each other to work. Dependency injection seems to be the solution to this and are used by some of the big frameworks around.

I've found Bucket on Github and have messed around it for a while to understand the basics. What I can't get my head around however is when it's appropriate to create a Container?

Making one big container including every possible class that may be needed seems nothing but counter-productive to me and I can't imagine that it is good practice. It seems like the recipe for bad performance at least.

In the alternative, which is to make multiple containers, I still don't get how the ever-stinking Singletons are not needed anymore.

Let's say that I would have the following code:

$session_container = new bucket_Container();
$session_container->create('Database');
$session_container->create('Database_Sessions');

$log_container = new bucket_Container();
$log_container->create('Database');
$log_container->create('Database_Log');

So here we have two containers, or in this case buckets for two totally different usages which are mutual by their dependency on the Database class.

My logic tells me that the above code will create two independent instances of the Database-class, meaning that I still would have to make the Database-class a singleton to ensure that concurrent instances of my database connection isn't occurring?

Is this correct?

解决方案

I don't know much about the specific lib, but assuming it lets you use a factory, let the factory return the same instance.

Edit: Ok, this is simply on the Bucket GitHub index page.

class MyFactory {
  function new_PDO($container) {
    return new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
  }
}

$bucket = new bucket_Container(new MyFactory());
$db = $bucket->get('pdo');

So in your case you could simply do:

class MyFactory {
   private $pdo;
   function new_Database($container) {
     if($this->pdo){
         return $this->pdo;
     }
     return $this->pdo = new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
   }
}
$factory = new MyFactory();

$session_container = new bucket_Container($factory);
$session_container->create('Database_Sessions');

$log_container = new bucket_Container($factory);
$log_container->create('Database_Log');

Something like that. Doesn't seem like rocket science.

Edit2: I don't have enough rep points to comment on the question (bit silly), but in response to your "modularity" concern: think of the container as the "glue" of your application. Indeed, if you have a large application, you may want to "glue" inside an isolated part of your application only. That is a valid encapsulation concern. But even then you still need a container that handles injection at the highest level of abstraction. If you just create a separate container for every part of your application, you either end up with unneeded duplication of instances, or you have to apply another level of instance management, which doesn't improve the encapsulation in any way: you're still sharing instances between different parts of your application.

My advice would be to use a single container at the bootstrap level. If you want added encapsulation for specific parts of your application (modules, plugins, whatever), use "child containers". A child container inherits the instances from the parent container, but the parent container knows nothing of the child (as far as he's concerned, he's still a bachelor ;)). Could be that Bucket supports this by default, I know other DI containers do. If not, it's really easy to implement using a Decorator. Imagine something like this:

class MyContainerType extends bucket_Container {

    private $_parent;
    private $_subject;

    public function  __construct($factory = null, bucket_Container $parent = null){
        $this->_parent = $parent;
        $this->_subject = new bucket_Container($factory);
    }

    public function get($key){
        $value = $this->_subject->get($key);
        if($value){
            return $value;
        }
        return $this->_parent->get($key);
    }
    /**
     * Override and delegation of all other methods
     */
}

这篇关于依赖注射在现实生活中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆