减少构造函数参数,同时明确保持服务使用?

sdg*_*sdh 2 oop design-patterns dependency-injection

我正在使用C#,但我的问题适用于任何OOP语言.

我有许多不同的对象,它们使用一系列服务.我想访问这些服务的方式来满足一些约束,但我正在努力找出一个好的设计.

  • 我希望这些服务的使用是明确的
  • 对象永远不应处于无效状态(服务应在构造时传递)
  • 服务使用应该清楚
  • 代码重复应该是最小的

我认为这些都是很好的目标,但事实证明它们难以实现.我目前的方法是一种依赖注入:

class MyObject
{
    // ... 

    public MyObject(IFooService fooService, IBarService barService)
    {
        this.fooService = fooService;
        this.barService = barService;
    }
}
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是当我有很多服务依赖项时会发生什么?我有几十个对象,其中一些需要访问许多服务.

我考虑构建一个"服务容器"对象并将其传递给:

class Services
{
    // ... 

    public IFooService FooService
    {
        get { return this.fooService; } 
    }

    public IBarService BarService
    {
        get { return this.barService; } 
    }

    public Services(IFooService fooService, IBarService barService)
    {
        this.fooService = fooService;
        this.barService = barService;
    }
}

class MyObject
{
    // ...

    public MyObject(Services services)
    {
        this.services = services;
    }
}
Run Code Online (Sandbox Code Playgroud)

这节省了输入,但它模糊了对象实际使用的服务.给定构造函数,MyObject可以使用它们中的任何一个!

  • 有哪些常见方法可以避免这个问题?
  • 我的问题是否表明更基本的设计问题?
  • 这真的是一个问题吗?我应该放松一些设计目标吗?

JB *_*zet 5

这可能表明存在两个问题

  1. 要注入的服务太细粒度(例如,如果你有一个服务来创建一个Foo,另一个服务来更新一个Foo,另一个服务来删除一个Foo),这导致了很多依赖.
  2. 或者,更可能的是,使用该服务的对象太粗糙,并且责任太多.例如,如果一半方法使用一组服务而另一半使用另一组服务,则可能很好地表明该对象可以分为两类.

无论如何,如果你认为你的课程不是太复杂,你可以阅读,维护和测试它,我不会太多关于依赖的数量.我更喜欢拥有清晰,明确的依赖关系,而不是依赖于作为服务工厂并取决于所有事物的上帝对象.这将损害可测试性和可读性.