创建新对象和依赖注入有什么区别?请详细解释。
它们不完全可比。你总是需要通过实例化一个类来创建新对象。但依赖注入也需要创建新对象。
当你想要控制或验证被你使用或测试的类所使用的实例的行为时,依赖注入真正发挥作用。(对于测试驱动开发来说,除了最小的示例外,依赖注入是至关重要的)。
假设有一个需要一个Handle类对象的Holder类。传统的做法是让Holder实例自己创建并拥有它:
class Holder {
private Handle myHandle = new Handle();
public void handleIt() {
handle.handleIt();
}
}
Holder实例创建了myHandle,没有任何类外部的代码可以访问该实例。在某些情况下,例如单元测试,这是一个问题,因为无法在不创建Handle实例的情况下测试Holder类,而Handle实例可能又依赖于许多其他类和实例。这使得测试变得笨重和复杂。
通过注入Handle实例,例如在构造函数中,外部代码将负责创建实例。
class Holder {
private Handle myHandle;
public Holder(Handle injectedHandle) {
myHandle = injectedHandle;
}
public void handleIt() {
handle.handleIt();
}
}
如你所见,代码几乎相同,而且Handle仍然是私有的,但Holder类现在与外部世界的耦合性更低,这使得许多事情变得更简单。并且在测试Holder类时,可以注入一个模拟或存根对象而不是实际实例,从而使验证或控制Holder、其调用程序和Handle之间的交互成为可能。
实际的注入将发生在其他地方,通常是一些“主要”程序。有多个框架可以帮助您在不编程的情况下完成此操作,但本质上这是“主要”程序中的代码:
...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...
本质上,依赖注入不过是一个高级版的set
方法。当然,你可以使用它来实现注入机制,而不是像上面简单的示例一样在构造函数中实现。
当然,两者都创建对象。不同之处在于谁负责创建。是需要其依赖项的类还是像Spring这样的容器,它连接组件的依赖项?您可以在单独的(通常是XML)配置文件中配置依赖关系。
这确实是一种关注点分离。类说我需要这个、这个和这个组件才能正常工作。类不关心如何获得其组件。您可以使用单独的配置文件将它们插入到类中。
举个例子,考虑一个需要支付模块的购物类。您不想硬编码将使用哪个付款模块。为了实现这一点,您反转了控制。您可以在容器的配置文件中用几个按键更改所使用的付款模块。优势在于您不需要修改任何Java代码。
创建一个新对象是非常明确的,你创建了一个所需类的新实例。
依赖注入是一种机制,为你提供需要的引用。想象一个表示连接到你的数据库的连接池的类 - 通常只有一个该类的实例。现在你需要将该引用分发到使用它的所有类中。这就是依赖注入派上用场的地方 - 通过使用Spring等DI框架,你可以定义一个连接池的实例将被注入到需要它的类中。
由于创建对象和依赖注入无法轻易地进行比较,因此你的问题本身并不容易回答...
SingletonClass.getSingleInstance()
返回一个具体的 SingletonClass
实例,你可以在代码的许多位置使用它。DI 通常会注入一个与 SingletonClass
签名匹配的接口 ISingletonClass
。你可以在创建 DI 的单一位置确定使用哪个具体实现。因此,在单元测试或不同平台上,你可以重复使用代码而不改变它,使用不同的 ISingletonClass
实现。 - Holger Böhnke依赖注入为您的应用程序增加了一层可配置性。当你硬编码对象构造时,你需要重新构建和重新部署你的应用程序,但是当你使用依赖注入时,你可以重新配置XML并改变行为而不需要重新构建和重新部署。有很多使用情况可以节省大量的时间和精力。
Holder
时,injectedHandle
如何在我们的控制之外被初始化呢?如果有更多的参数,它如何知道如何初始化它们,或者根本不初始化它们? - Yoda