在阅读了这个问题How to avoid Dependency Injection constructor madness?后,我仍然对我的应用程序设计有些担忧。假设我有一个类,它的构造函数中包含很少的参数:
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法。
所以问题是:我应该如何减少不相互通信的构造函数依赖项的数量,只暴露属性而不是内部逻辑呢?
答案 0 :(得分:0)
从几个不同的角度来看待它:消费者和更高层次的设计。
不喜欢有这么多的合作者吗?也许如果它有druthers,它只会有一个合作者。那个合作者看起来怎么样?为它创建一个interface to represent the role。
例如:
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
个对象? IReader1
,IReader2
和IReader3
经常一起使用吗? IReader1
和IReader3
怎么样?
提出这个问题的关键是识别“隐藏的”抽象,以便使它们更加明确。如果某些物体经常串联使用,它通常代表更广泛的设计概念。
但有时a rose is a rose is a rose。也许SampleViewModel
是唯一使用IReaderX
对象的东西。也许SampleViewModel
的唯一责任是聚合个体读者。在这些类型的情况下,拥有多个合作者并没有错。
如果稍后添加了其他协作者(例如IReader4
),则应再次进行所有此评估。有时设计恰好跳出来。