dependency-injection - 减少依赖数量的好方法是什么?

标签 dependency-injection

我使用依赖注入(inject)已经有一段时间了,我真的很喜欢这种技术,但我经常遇到一个问题,即应该注入(inject) 4 - 5 次的依赖项太多,这看起来太多了。

但我找不到使它更简单的方法。例如,我有一个包含一些发送消息的业务逻辑的类,它接受另外两个业务逻辑依赖项来执行所需的操作(一个将数据转换为发送的消息,一个转换接收到的消息)。

但除此之外,它还需要一些“技术”依赖项,如 ILoggerITimerFactory(因为它需要在内部创建计时器)、IKeyGenerator (生成唯一键)。

因此整个列表变得非常大。有什么好的通用方法可以减少依赖项的数量吗?

最佳答案

处理这些问题的一种方法是重构聚合(或门面)。 Mark Seemann 写了一篇关于它的好文章,check it out (实际上我也强烈推荐 his book,只是说)。 假设您有以下内容(摘自文章):

public OrderProcessor(IOrderValidator validator,
                      IOrderShipper shipper,
                      IAccountsReceivable receivable,
                      IRateExchange exchange,
                      IUserContext userContext)

您可以将其重构为:

public OrderProcessor(IOrderValidator validator,
                      IOrderShipper shipper,
                      IOrderCollector collector)

其中 OrderCollector 是一个外观(它包装了前面的 3 个依赖项):

public OrderCollector(IAccountsReceivable receivable,
                      IRateExchange exchange,
                      IUserContext userContext)

希望对您有所帮助。

编辑

就横切关注点(例如日志记录和缓存)和处理它们的策略而言,这里有一个建议(这是我通常做的),假设你有以下内容:

public interface IOrderService
{
    void DoAwesome();
}

public class OrderService : IOrderService
{
    public void DoAwesome()
    {
        // do your thing here ... no logging no nothing
    }
}

在这里,我将使用装饰器模式来创建一个启用了日志记录的 OrderService:

public class OrderServiceWithLogging : IOrderService
{
    private readonly IOrderService _orderService;
    private readonly ILogger _logger;

    public OrderServiceWithLogging(IOrderService orderService, ILogger logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    public void DoAwesome()
    {
        _orderService.DoAwesome();
        _logger.Log("Awesome is done!");
    }
}

它可能看起来有点开销,但恕我直言,它很干净且可测试。

另一种方法是进入面向方面的编程并研究诸如拦截之类的概念,基本上您拦截某些方法调用并执行任务作为结果。许多 DI 框架(我想说全部?)都支持拦截,所以这可能是您更喜欢的。

关于dependency-injection - 减少依赖数量的好方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18204113/

相关文章:

java - Spring - 两个实现之间的运行时选择

php - 在 Sonata Admin Bundle 中注入(inject)容器服务的正确方法

swift - Swinject:使用元类型列表进行解析

Symfony 3 - 具有多个数据库连接的 EntityManager 依赖注入(inject)

c++ - 使用 X3 的解析器依赖注入(inject)

asp.net - 使用 2 个参数注入(inject)构造函数不起作用

Maven : Modifying the manifest files of dependency JARs

c# - Unity选择带参数的构造函数

c# - 使用 ResolveUnregisteredType 事件在 Simple Injector 中注入(inject)可能会根据请求更改的数据库配置值

java - 当可以导入 java 类时为什么要使用依赖注入(inject)?