我应该选择依赖注入还是工厂模式?

5

我正在调查依赖注入。我发现:在大多数引用依赖注入用法的示例中,我们也可以使用工厂模式来解决问题。

请帮我比较一下依赖注入和工厂模式的优缺点。我应该始终选择依赖注入而不是工厂模式吗?还是这取决于具体的项目?

如何确定最佳解决方案?这方面有什么最佳实践吗?


你能否展示这两种模式的例子?这将有助于理解你打算如何使用它们。 - Steven
5个回答

5
让我们看一下它们之间的区别。 使用DI,对象是外部创建的并且被“注入”到客户端对象中供其使用。 通常使用构造函数进行注入。 然而,在复杂情况下,常见的是注入一个DI容器来创建依赖对象,包括所有子依赖关系。所以它看起来像抽象工厂! 使用抽象工厂,一个具体工厂类的实例被注入,依赖对象由客户端对象实例化。 因此,当你考虑到在这两种情况下,工厂对象都被传递给客户端以使其能够创建其依赖关系时,DI和抽象工厂基本上是相同的。 只有在简单情况下,依赖对象才被外部创建并传递给客户端对象。这就是策略模式的工作方式。 由于DI容器现在如此普遍,并且在框架中被广泛使用,它们已经取代了抽象工厂,至少作为一个经常谈论的模式。 DI容器比抽象工厂更为复杂(我相信)。 因此,没有最佳实践!

4

你应该同时使用工厂模式和依赖注入。

工厂模式的作用是根据给定参数找到接口的正确实现,并返回其实例。它是解决一个类既要实例化自己又要做其他事情的问题的一种方式,因为这会违反SRP原则。

依赖注入通常是通过将参数传递给实际类的构造函数来注入依赖项。需要这样做是因为高级代码不应该知道它使用低级代码的哪个实现,而只需要知道该实现与某个接口对应。否则,我们将违反DIP原则。

因此,工厂模式非常适用于依赖注入。实际上,依赖注入容器只是一个自动化工厂,它从注释、配置文件等中提取信息,以能够创建应用程序实例并注入其依赖项。当然,它的依赖项也有依赖项,依此类推,如果你手动编写代码,它将变得很长,可能成为一个god对象。你可以通过定义工厂来解决这个问题,这将使代码更加简短明了,但某种程度上人们更喜欢自动化。


在这个上下文中,“dependency”是什么意思? - Soner from The Ottoman Empire
@snr 嗯,依赖性是一个广泛的概念。通常它只是指代码的一部分依赖于另一部分代码。在某些语言中,您可以将依赖项作为参数传递给依赖代码,例如函数名称、lambda函数、对象等。当我们有许多具有共同接口(例如函数的公共参数列表或对象的公共接口)的替代实现,并且我们想在它们之间进行选择时,我们就会这样做。依赖注入是当我们将其作为构造函数或设置器参数传递时。在DI容器的情况下,我们根据配置选择依赖项。 - inf3rno

2

@pcperth:来自Xamarin University的消息,他们提到两者都有优缺点:

enter image description here

enter image description here

此外,我认为使用DI时,类是首先创建的,我们的程序在运行期间保持这些类,这可能会浪费内存(如果我们需要优化内存)。
这是我的观点,但实际上我不知道哪种方法更好或者在特定情况下应该使用哪种方法。因此我需要一些讨论。
加油!

1
我喜欢使用简单的接口依赖注入。 只需将实现该接口的对象传递给构造函数即可。
这样做的额外优势是,您可以轻松地模拟接口并在构建服务器/计算机上运行测试。由于使用Xamarin部署非常耗时,请尽可能多地使用单元测试。

1
这是我遵循的经验法则:如果实例化需要在运行时才能获得参数(例如用户输入),则使用工厂模式。否则,请使用 DI。请注意,工厂本身应通过 DI 访问。
例如,用户可以选择生成饼图或条形图。但是,两者都使用某种数据访问服务 - 比如 DataAccessContext。ChartFactory 将如下所示。
DataAccessContext context {get; set;}
public ChartFactory(DataAccessContext context) //Comes from DI
{
   this.Context = context;
}

public Chart GetInstance(string type) // Factory instance
{
  if(type == "Pie")
    return new PieChart(context);
  if(type == "Bar")
    return new BarChart(context);
  throw new ArgumentException("Invalid choice");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接