依赖注入&构造函数疯狂修正

本文关键字:疯狂 构造函数 注入 依赖 | 更新日期: 2023-09-27 18:13:23

看完这个问题如何避免依赖注入构造函数的疯狂?我对我的应用程序设计还有一些顾虑。假设我有一个类,它在构造函数中接受几个参数:

public class SampleViewModel
{
    public SampleViewModel(IReader1 reader1, IReader2 reader2, IReader3 reader3)
    {
        // ...
    }
}

IReaderX是一个从不同来源检索数据的接口,它看起来像这样:

public interface IReader1
{
    int Value1 { get; }
    string Value2 { get; }
}

现在,如果我想将这些接口聚合成一个,我就必须创建另一个类,比如ReaderManager,它将充当底层类属性的包装器。大量的管道代码。如果你问我的话,我觉得不太好。

我尝试使用Composition并将所有读取器作为ReaderManager类的属性,但如果我试图在外部使用这些读取器,我会违反Demeter定律。

所以问题是:我应该如何减少构造函数依赖的数量,不相互通信,只暴露属性,而不是内部逻辑?

依赖注入&构造函数疯狂修正

从两个不同的角度来看:消费者和更高层次的设计。


从' SampleViewModel '的角度看

它不喜欢有这么多合作者吗?也许如果它有自己的选择,它只会有一个合作者。这个合作者会是什么样子?创建一个接口来表示它的角色。

例如:

public interface ISampleViewModelReader
{
    int Value1    { get; }
    string Value2 { get; }
    double Value3 { get; }
    string Value4 { get; }
}
public class AggregatedSampleViewModelReader : ISampleViewModelReader
{
    public AggregatedSampleViewModelReader(IReader1 reader1, IReader2 reader2, IReader3 reader3)
    {
        // ...
    }
    // ...
    double Value3 { get { return reader2.Value3; } }
    // ...
}
public class SampleViewModel
{
    public SampleViewModel(ISampleViewModelReader reader)
    {
        // ...
    }
}

你指出你对这种方法有顾虑,因为它会涉及"大量的管道代码"。但是考虑到这些管道代码将在有或没有包装器类的情况下存在。通过定义包装器类,至少可以确定一个对象,它的唯一职责是处理这个管道,而不是将其混合到SampleViewModel的其他职责中。


从更高层次的设计角度看

其他对象如何使用IReaderX对象?IReader1IReader2IReader3经常一起使用吗?IReader1IReader3呢?

问这个问题的目的是识别"隐藏的"抽象,以便使它们更显式。如果某些对象经常串联使用,它通常代表了更广泛的设计概念。

但有时玫瑰就是玫瑰。也许SampleViewModel是唯一使用IReaderX对象的东西。也许SampleViewModel唯一的责任就是集合个人读者。在这种情况下,有几个合作者并没有什么错。

如果稍后添加了另一个合作者(例如,IReader4),那么所有这些评估都应该再次进行。有时候设计就是突然出现在你眼前。