简体   繁体   English

类构造函数应该只用于依赖注入吗?

[英]Should class constructors only be used for dependency injection?

There are two major ways that class constructors can populate their class' dependencies:类构造函数可以通过两种主要方式填充其类的依赖项:

  1. Populate the class dependencies by constructor dependency injection.通过构造函数依赖注入填充类依赖。
  2. Populate the class dependencies by using the constructor parameters to run some calculations in the constructor.通过使用构造函数参数在构造函数中运行一些计算来填充类依赖项。 The dependencies are instantiated based on the calculation results.根据计算结果实例化依赖关系。 This may involve use of new .这可能涉及使用new

I am wondering if the second method adheres to good coding practices such as the Single Responsibility Principle, and if that sort of functionality really belongs in a class constructor.我想知道第二种方法是否遵循单一职责原则等良好的编码实践,以及这种功能是否真的属于类构造函数。 It seems convenient, but I am not sure if it is a good idea.看起来很方便,但我不确定这是否是个好主意。

Here's an example of what I mean:这是我的意思的一个例子:

public class VectorSpace
{
    // This class depends on an array of Vectors.
    Vector[] spanningSet;

    // 1. Populate the class dependencies by constructor dependency injection.
    public VectorSpace(Vector[] spanningSet)
    {
        this.spanningSet = spanningSet;
    }

    // 2. Populate the class dependencies by running some calculations in the constructor.
    public VectorSpace(Rect rectangle, int numberOfCellsX, int numberOfCellsY)
    {
        // Construct this class to make sure the resulting vector space fits the given rectangle, forming a grid.
        // Some calculations that ultimately populate the class dependencies go here...
    }

    // Public methods for performing calculations using the Vectors go here...
}

It feels odd because making the vector space fill a grid feels like a job that is outside the scope of this class, but I don't know where else I would define this second constructor.感觉很奇怪,因为让向量空间填充网格感觉就像是在这个类的范围之外的工作,但我不知道我还能在哪里定义第二个构造函数。

Is the functionality of the second constructor appropriate to be in this class?第二个构造函数的功能是否适合在这个类中? If not, where would I move this constructor body to?如果没有,我会将这个构造函数体移到哪里? Should I use a static factory method instead?我应该使用静态工厂方法吗? Should I make this constructor be the constructor of a different class?我应该让这个构造函数成为不同类的构造函数吗? Maybe I could have a similar method somewhere that returns an array of Vectors that I could pass into the dependency injection constructor, but where would I define that method?也许我可以在某处有一个类似的方法来返回一个向量数组,我可以将它传递给依赖注入构造函数,但是我应该在哪里定义该方法?

VectorSpace class depends on the data (set of vectors), but data can be provided/calculated in many ways. VectorSpace类取决于数据(向量集),但可以通过多种方式提供/计算数据。
Will logic of VectorSpace change if you will change how vectors should be calculated/retrieved?如果您将更改矢量的计算/检索方式, VectorSpace逻辑会发生变化吗? I assume not - so it is shouldn't be part of the VectorSpace class.我认为不是 - 所以它不应该是VectorSpace类的一部分。

We can create dedicated class which will be responsible to calculate required data.我们可以创建专门的类来负责计算所需的数据。

public class SpanningSetFactory
{
    public Vector[] Create(Rect rectangle, int numberOfCellsX, int numberOfCellsY)
    {
        // Calculate and return set of vectors
    }
}

Now VectorSpace can explicitly "tell" other developers/readers that it depends only on the set of vectors现在 VectorSpace 可以明确地“告诉”其他开发人员/读者它只依赖于向量集

public class VectorSpace
{
    public VectorSpace(Vector[] spanningSet) => _spanningSet = spanningSet
}

Now both logics "Calculate spanning set" and "Use spanning set" will be in their own locations without dependency on each other - only dependency link they have with each other will be array of Vector现在,“计算生成集”和“使用生成集”这两个逻辑都将位于它们自己的位置而不相互依赖 - 只有它们彼此之间的依赖链接将是Vector数组

I would suggest to avoid putting some calculations(especially heavy ones) in the constructor.我建议避免在构造函数中放置一些计算(尤其是繁重的计算)。
Good help for other developers will be when critical logic(calculations, data retrieving) is explicitly visible in forms of methods or other types.当关键逻辑(计算、数据检索)以方法或其他类型的形式显式可见时,对其他开发人员有很好的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM