2014-02-27 143 views
4

我知道一些OOP和已经阅读这个那个,但我不是一个铁杆OOP的家伙,有没有正规的训练,不能背出为什么有些东西应该使用依赖注入或没有,可能无法识别设计中的所有依赖关系,因此我的问题。OOP依赖关系:依赖注入与注册

在这里回答问题SO(Using a object in methods of other objects),我开始怀疑自己。至于依赖关系,其中一个更好还是更糟,或者两者都可以接受?任何设计限制?

我已阅读并理解这两种,但还未曾遇到过的比较。为什么会一个是在设计中更好地使用等

依赖注入:

class myClass { 
    private $db; 

    public function __construct($db) { 
     $this->db = $db; 
    } 
} 

注册(也许还有其他方面):

class myClass { 
    private $db; 

    public function __construct() { 
     $this->db = Registry::get('db'); 
    } 
} 
+0

两者都不是更好或更坏。就我个人而言,我更喜欢第一个,因为IMO尽可能隐藏您的输入参数,最终使得调试变得更加困难。 – Tularis

+0

是的:)但我没有意识到链接指向德国文章..对不起:)让我们检查一下,如果我可以找到其他的东西... – hek2mgl

+0

@ hek2mgl:这是有道理的(当我将它翻译为我的Deutsch ist klein) – AbraCadaver

回答

5

这两种方法都可以实现的依赖注入。基本上,依赖注入意味着定义一种方法来配置(注入)要在运行时使用的类,以便使代码更灵活,而不是在代码中使用硬编码的类名和构造函数。依赖注入遵循一个称为inversion of control的原则。

这对于测试代码尤其是有趣的,但可以在不同的地方要提出申请,灵活和易于维护等情况下使用。

虽然依赖注入大多作为DI container称为,它通常可使用几个不同的方法来完成 - 其也可以共存。使用利用设定器依赖注入容器

  • 通类依赖性,使用中央注册表构造方法或方法ARGS
  • (只要它是可配置的)
    • :这里谈到的(不完全的)列表方法
    • 使用配置文件来设置依赖
    • 用户输入
    • ...
  • +0

    这是一个完美的答案。 – abnvp

    +0

    依赖依赖注入器容器的注册表类如何?这可能是两全其美吗? –

    6

    它与可测性有很大关系。

    在你的例子中,第一个(依赖注入)更好。它的更好的原因是因为它接受db作为参数,这意味着这是可检验的,可以使用一个模拟db用于测试和测试myClass做正确的事吧。

    第二个例子(注册)不推荐,因为不仅myClass取决于db,现在也要看Registry,而最糟糕的是,它知道如何获得db。它太聪明了,它应该像第一个一样愚蠢,愚蠢的东西更容易测试,聪明的东西不是。

    +0

    在第二种情况下,也应该能够模拟注册表并将其用于测试。我相信它与个人偏好和开发人员正在使用的DI框架有关 – abnvp

    3

    需要依赖注入,因为对象需要某些数据才能正确执行其功能。

    依赖注入可以用三种不同的方式进行:

    • 如果对象A依赖对象B上,那么你就可以创建对象的同时创建对象B
    • 你可以使用一些外部类(如注册表,配置文件等)来加载依赖项对象,这将使对象的创建与创建依赖关系分离。这称为定位器模式,其中您的对象创建依赖于定位器来加载对象。
    • 您可以在别处创建依赖项并将其直接提供给依赖对象。这就是所谓的 '手动进样'

    每当你做这些,你已经做的依赖注入:

    构造方法注入

    public class ClassA 
    { 
    // declares the dependency in the constructor 
    
    public function ClassA(dependency1:String) 
    {} 
    } 
    
    // and the dependency is created while instantiating the object 
    var objA:ClassA = new ClassA("Hello World"); 
    

    公共属性注入

    public class ClassA 
    { 
    // declares the dependency as a public property 
    public var helloStr:String; 
    } 
    
    var obj1:ClassA = new ClassA(); 
    
    // dependency is fulfilled by setting a public property after instantiation: 
    obj1.helloStr = "The Zen Master";