Spring——依赖注入和工厂模式的区别
依赖注入和工厂模式在某种意义上几乎相似,它们都遵循接口驱动的编程方法并创建类的实例。
A. 工厂模式
在Factory Pattern中,客户端类仍然负责通过工厂类的getInstance()方法获取产品的实例,这意味着客户端类与工厂类直接耦合,没有工厂类就无法进行单元测试。
实现:在这个例子中,我们将借助 ExpenseTracker 应用程序来区分工厂模式和 DI。在这个应用程序中,我们有一个依赖类 ExpenseTracker,它依赖于 ExpenseCalculator 类。在这里,我们将同时使用工厂模式和依赖注入来了解它们之间的区别。
例子:
Java
// Java Program to Illustrate Factory Pattern
// Dependent class
public class ExpenseTracker {
// Getting instance of ExpenseCalculator class
// using Factory class method
private ExpenseCalculator expenseCal
= ExpenseCalculatorFactory.getInstance();
// Method
public void add(Transaction transaction)
{
// Returns the expense amount
// of ExpenseCalculator class
int expense
= expenseCal.getTransactionAmount(transaction);
add(expense);
}
}
Java
// Java Program to Illustrate Dependency Injection
// Dependent class ExpenseTracker
public class ExpenseTracker {
// Class data member
private ExpenseCalculator expenseCal;
// Constructor
// Dependencies are injected
// using Constructor Dependency Injection
public ExpenseTracker(
ExpenseCalculator expenseCalculator)
{
// This keyword refers to current instance itself
this.expenseCal = expenseCalculator;
}
// Method
public void add(Transaction transaction)
{
int expense
= expenseCal.getTransactionAmount(transaction);
add(expense);
}
// Dependencies are injected
// using Setter Dependency Injection
public void setExpenseCalculator(
ExpenseCalculator expenseCalculator)
{
this.expenseCal = expenseCalculator;
}
}
代码说明:在上面的示例中,我们可以看到我们的依赖类ExpenseTracker直接与ExpenseCalculatorFactory耦合,因为它调用ExpenseCalculatorFactory类的静态getInstance()方法以满足其依赖关系。如果我们要测试 ExpenseTracker 类,就必须有 ExpenseCalculatorFactory 类,它不适合 ExpenseTracker 类的单元测试,使得单元测试更加困难。
另一方面,如果我们将使用 DI,那么依赖项是由 Spring 框架或 DI 容器添加的,因为我们颠倒了获取依赖项的职责。这将使 IOC 容器负责注入依赖项而不是依赖类,并且它将任何客户端或依赖类看起来变成 POJO 类。
B. 依赖注入
在依赖注入 (DI) 的情况下,客户端不知道如何创建和管理依赖项。客户端类只知道依赖关系,并且大部分依赖关系是由 IOC 容器注入的。例如,Bean 类的存在没有任何硬编码依赖,它们由 IOC 容器(如 Spring Framework)注入。
例子:
Java
// Java Program to Illustrate Dependency Injection
// Dependent class ExpenseTracker
public class ExpenseTracker {
// Class data member
private ExpenseCalculator expenseCal;
// Constructor
// Dependencies are injected
// using Constructor Dependency Injection
public ExpenseTracker(
ExpenseCalculator expenseCalculator)
{
// This keyword refers to current instance itself
this.expenseCal = expenseCalculator;
}
// Method
public void add(Transaction transaction)
{
int expense
= expenseCal.getTransactionAmount(transaction);
add(expense);
}
// Dependencies are injected
// using Setter Dependency Injection
public void setExpenseCalculator(
ExpenseCalculator expenseCalculator)
{
this.expenseCal = expenseCalculator;
}
}
代码说明:我们可以看到ExpenseCalculator的依赖是使用类的构造函数注入到ExpenseTracker类中的,这叫做构造函数依赖注入。此外,我们可以使用 Setter 方法注入依赖项,我们也可以在上面的代码中看到,它称为 Setter Dependency Injection。
依赖注入和工厂模式的区别
Dependency Injection | Factory Pattern |
---|---|
DI is only aware of the dependencies. It does not know anything about the container or factory. | It adds coupling between objects, factory, and dependency. It requires both a dependent object and a factory object to work properly. |
DI makes the unit tests easier. It does not require boilerplate code. | The factory pattern requires the object you want to test, the factory object, and the dependent object. |
DI is more flexible than factory patterns. It also gives the facility to switch different DI frameworks such as Spring IOC and Google Guice. | It is not much flexible as Dependency Injection. |
DI requires a container and configuration in order to inject dependencies. | The factory pattern does not require these configuration steps. |
Due to less coupling, the result of DI is much cleaner. The client class looks like the POJO class. | In the case of the Factory pattern, the client class is not clean as in DI. |