Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 依赖注入&;疯狂建造师修订_C#_Design Patterns_Dependency Injection - Fatal编程技术网

C# 依赖注入&;疯狂建造师修订

C# 依赖注入&;疯狂建造师修订,c#,design-patterns,dependency-injection,C#,Design Patterns,Dependency Injection,在阅读了这个问题之后,我仍然对我的应用程序设计有一些担忧。假设我有一个类,它的构造函数中只有很少的参数: public class SampleViewModel { public SampleViewModel(IReader1 reader1, IReader2 reader2, IReader3 reader3) { // ... } } IReaderX是一个用于从不同来源检索数据的接口,如下所示: public interface IReade

在阅读了这个问题之后,我仍然对我的应用程序设计有一些担忧。假设我有一个类,它的构造函数中只有很少的参数:

public class SampleViewModel
{
    public SampleViewModel(IReader1 reader1, IReader2 reader2, IReader3 reader3)
    {
        // ...
    }
}
IReaderX
是一个用于从不同来源检索数据的接口,如下所示:

public interface IReader1
{
    int Value1 { get; }

    string Value2 { get; }
}
现在,如果我想将这些接口聚合成一个接口,我必须创建另一个类,比如说
ReaderManager
,它将充当底层类属性的包装器。很多管道规范。不好,如果你问我的话

我尝试使用Composition并将所有读卡器作为
ReaderManager
类中的属性,但如果我试图在外部使用这些读卡器,我将违反德米特定律


所以问题是:我应该如何减少构造函数依赖项的数量,这些依赖项彼此不通信,只公开属性,而不公开内部逻辑?

从两个不同的角度来看待它:消费者和更高级别的设计


从` 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
对象?
IReader1
IReader2
IReader3
经常一起使用吗?那么
IReader1
IReader3

提出这个问题的目的是识别“隐藏的”抽象,以便使它们更加明确。如果某些对象经常串联使用,它通常代表更广泛的设计概念

但是有时候。可能只有
SampleViewModel
使用了
IReaderX
对象。也许,
SampleViewModel
的唯一责任就是聚合各个读者。在这种情况下,有几个合作者没有什么错


如果以后添加了另一个协作者(例如,
IReader4
),则应再次进行所有评估。有时设计会突然跳出你的视线。

你的视图模型能被分割成需要较少参数的较小视图模型吗?不太可能。这是核心视图模型,从应用程序开始,管理其他窗口。它必须使用来自所有读卡器的验证数据,并在此基础上更改视图的状态。是否存在不同数据源的接口也不同的原因,是否存在由所有数据源实现的单一接口,因此,您可以使用一个接口的列表作为依赖项?每个接口从不同的源读取不同的数据。它们有很多属性,将它们绑定在一起会导致一个巨大的类,这也违反了SRP。很难说,因为您发布的代码非常通用,并且没有揭示ViewModel的职责。但是如果你的读者非常不同,Ned Stoyanov建议考虑拆散视图模型的建议听起来是正确的。即使你对它的描述听起来也似乎有太多的责任(启动应用程序、管理窗口、加载数据、验证、更改视图状态)。这让我想起mark seemann blog bost泄漏的抽象:这也是:问题是所有
IReaderX
实例都是单独使用或一起使用的,具体取决于消费者。似乎没有一个好的解决办法。如果我不想为特定属性创建许多小包装器,那么我必须创建一个大包装器类,这反过来违反了SRP。我所说的管道代码是指多个属性包装器,通过显式使用读取器可以避免这种情况。我必须使用现有的体系结构来设计我的部分应用程序,也许问题在于更高层次的系统设计。@MarekKowalczyk然后几乎可以肯定还有一些抽象尚未确定。
IReaderX
对象被用作达到某种目的的手段。也就是说,他们是“如何”做某事的“什么”。(由于不同的事物以不同的方式使用它们,每种情况都可能代表一个识别抽象的机会。)一个有助于识别抽象的问题可能是:“当某件东西从
IReader1
获得
Value1
后,它会被用来做什么?”@Lilshieste Ok,也许我们应该考虑实际的例子。我有三个读卡器,我在视图模型中使用它们来更改其视觉状态,即视图。但首先我需要执行验证,检查所有读卡器中的数据是否正确加载。这不是一个简单的逻辑,所以我需要另一个人来做这项工作,比如说
ReaderValidator
。它具有事件
DataValidated
,该事件在异步验证后激发。但我仍然需要这些读者。您将如何在视图模型中构建这样的逻辑?考虑到ofc,我们需要避免构造函数疯狂并遵守SRP。@MarekKowalczyk,目前调用
ReaderValidator
?视图模型?