Answers:
避免教条。做正确的事。
我更喜欢对没有行为的数据结构使用“ new”。
如果该类确实有行为,那么我将研究该行为的范围。如果它是无状态的并且没有依赖项,那么我倾向于“新”。我仅在需要向有状态资源(例如数据库或文件)或具有此类资源的其他类添加依赖项时才开始对DI进行重构。
new
在我自己的代码中显示“ ed依赖性”,这提示了我的问题。这是一个简单的类,本身没有功能或“行为”,只有简单的属性。
在我的书中,我对稳定依赖项和不稳定依赖项进行了区分。将DI与易失性依赖关系一起使用是最重要的,但是通常您也可以通过抽象和注入稳定依赖关系来实现更宽松的耦合。
请记住,DI的应用程序不应依赖DI容器。在使用穷人DI的情况下,不会new
删除任何关键字-它们只会移至“ 合成根目录”。
实际上,有些人更喜欢穷人的DI,而不是DI容器。维护成本可能会更高,但是您可以获得编译时的安全性。正如我最近听到的Dan North所说:“ new
是新的new
” :)
这意味着它不是仅用一堆嵌套new
语句来代替用DI容器实现“合成根”,而是简单地代替。
“ new”不是禁止的关键字。我的个人规则:
所有“服务”(我将服务称为旨在提供一种或多种与一件事情有关的方法的类;例如:访问数据库,检索/更新与给定域有关的数据)已注册在IOC容器中。无需任何类来决定如何获取需要使用的给定服务的实现。因此,每当需要使用现有服务时,都应配置您的类和IOC容器以将其提供给您。想象一下,您不知道实现的工作原理,它可能是Web服务,您不在乎。
当我需要启用所有默认属性时,将使用“ new”关键字或使用IOC注册的工厂来创建所有bean或模型。实用程序类也有特殊情况,它仅包含静态方法(例如:数学实用程序服务)。如果它们是完全独立的,并且不需要任何数据库连接或其他IOC注册的服务,则可以将它们放在IOC之外,并将其静态调用。但是,如果一个此类需要使用现有的IOC注册服务,则将其更改为单例类并在IOC中注册。
我只想添加到earler提出的现有答案中,就new
可以创建纯值对象(即仅具有属性/获取器/设置器)的对象。有关更多详细信息,请参见Google测试博客。
new
“编
显然取决于您使用的语言。如果您的语言强迫您使用对象来表示实际对象和记录(值对象,结构),那么答案很可能不是。
纯粹说“真实”对象,显式创建实例没有错。但是,您必须记住的是,所有课程都应遵循单一责任原则。选择类所依赖的服务的实现者不是类的责任。但是,有些班级对此负有很大责任,即提供某些服务的实现者。IoC可能就是此类。实际上,任何类型的工厂都属于此类。
总结一下:只有这样的类才应直接实例化对象,由谁负责选择要实例化的类。
您可能会发现这些条件很有帮助:http : //en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator
一个字:不。
更多的话:依赖注入就是这样。通过这种方法,您可以从另一个来源介绍另一个对象所依赖的资源,但不应了解其复杂的细节。使用DI并不意味着程序中的NOTHING应该不知道如何创建任何其他对象。实际上,我认为非平凡的程序完全避免使用“ new”关键字(或基于反射的替代方法)是不可行的。但是,DI确实意味着那些不应该知道如何创建需要大量依赖关系的复杂对象的对象将这些对象紧密地耦合到另一个对象,而不应该具有所有这些紧密耦合的知识。
我将研究O / O软件设计的两个主要理论,即GRASP和SOLID。GRASP会告诉您研究对象的目的,并问自己:“该对象是否应负责创建其他类型的新对象?这是该对象的“工作描述”的一部分吗?” SOLID进一步迈进了一步:“ S”代表“单一责任原则”,该原则明确声明一个对象应该有一个工作,并且它应该是程序中唯一可以完成该特定工作的对象。
因此,GRASP通常会鼓励您浏览创建这些新对象的现有类,并在创建所需对象的同时,在保持所需“凝聚力”的同时找到创建该对象的任务与该对象已经完成的工作相适应的类。SOLID会告诉您凝聚力是关键;创建这些对象的任务应该交给应该注入您的类的工厂。我想您会发现,随着程序复杂度的不断提高,遵循这两种方法中的任何一种,并且愿意进行重构,都将导致非常类似的体系结构。