C# 构造(有点)复杂的对象

C# 构造(有点)复杂的对象,c#,.net,constructor,dns,C#,.net,Constructor,Dns,当我创建类时,简单的构造函数往往是标准的。在我当前的一个项目,电影库中,我有一个movie域对象。它具有多个属性,从而生成一个构造函数,如下所示: public Movie(string title, int year, Genre genre, int length, IEnumerable<string> actors) { _title = title; _year = year; _genre = genre; _length = length

当我创建类时,简单的构造函数往往是标准的。在我当前的一个项目,电影库中,我有一个
movie
域对象。它具有多个属性,从而生成一个构造函数,如下所示:

public Movie(string title, int year, Genre genre, int length, IEnumerable<string> actors)
{
    _title = title;
    _year = year;
    _genre = genre;
    _length = length;
    _actors = new List<string>(actors);
}
公共电影(字符串标题、整数年、类型、整数长度、IEnumerable演员)
{
_头衔=头衔;
_年=年;
_体裁=体裁;
_长度=长度;
_参与者=新列表(参与者);
}
这并不可怕,但也不简单。使用工厂方法(
staticmoviecreatemovie(…)
)或对象生成器是否值得?是否存在实例化域类的典型模式


更新:感谢您的回复。起初我可能想得太多了,不过我学到了一些在更复杂的情况下有用的东西。我现在的解决方案是将title作为唯一必需的参数,其余的作为命名/可选参数。这似乎是构建此域对象的理想方法。

您对自己的问题给出了很好的答案,这是工厂模式。使用factory模式,封装不需要庞大的构造函数,您可以在factory函数中设置对象的成员并返回该对象。

这是完全可以接受的,IMHO。我知道静态方法有时是不受欢迎的,但我通常会将该代码放入一个返回类实例的静态方法中。我通常只对允许有空值的对象这样做


如果对象的值不能为null,请将它们作为参数添加到构造函数中,这样就不会出现任何无效对象。

视情况而定。


如果这是该类的唯一构造函数,则意味着实例化对象需要所有属性。如果这符合您的业务规则,那就太好了。如果没有,可能会有点麻烦。例如,如果你想在你的系统中植入电影,但并不总是有演员,你可能会发现自己陷入困境

您提到的CreateMovie()方法是另一个选项,以防您需要将内部构造函数与创建电影实例的行为分开


您有许多选项可供您安排构造函数。使用那些可以让您在设计系统时不带任何气味和大量原理的方法(DRY、YAGNI、SRP)。

是的,使用工厂方法是一种典型的模式,但问题是:您为什么需要它?这就是工厂方法的特点:

与其他创建模式一样,它处理创建对象(产品)的问题,而不指定要创建的对象的确切类别。factory方法设计模式通过定义用于创建对象的单独方法来处理此问题,然后子类可以重写该方法以指定将要创建的产品的派生类型

因此,如果您想返回
Movie
的子类,那么工厂方法模式是有意义的。如果这不是(也不会是)一项要求,那么用工厂方法替换公共构造函数实际上没有任何用处


对于您问题中所述的要求,您的解决方案在我看来非常好:所有必填字段都作为参数传递给构造函数。如果没有必填字段,则可能需要添加默认初始值设定项并使用。

如果使用.NET 4.0,可以用来简化接受多个参数的对象的创建,其中一些参数是可选的。当您希望避免许多不同的重载以提供有关对象的必要信息时,这非常有用

如果您不在.NET 4上,您可能需要使用该模式来组装您的类型。Object builder需要花费一些精力来实现,并与您键入的内容保持同步——因此,这样做是否有足够的价值取决于您的情况


我发现构建器模式在组装层次结构时最有效,而不是一个具有一系列属性的类型。在后一种情况下,我通常使用重载或可选/命名参数。

我看不出构造函数的接口有任何问题,也看不出静态方法会给您带来什么。我会有完全相同的参数,对吗

这些参数似乎不是可选的,因此没有一种方法可以为重载提供更少或更少的参数 使用可选参数

从调用者的角度来看,它看起来像这样:

 Movie m = new Movie("Inception", 2010, Genre.Drama, 150, actors);
工厂的目的是为您提供一个可定制的具体接口实例,而不仅仅是为您调用构造函数。其思想是,在构造时不需要硬编码确切的类。这真的更好吗

 Movie m = Movie.Create("Inception", 2010, Genre.Drama, 150, actors);
我觉得差不多。唯一更好的是,如果
Create()
返回了比
Movie
更具体的类

需要考虑的一件事是如何改进这一点,以便调用代码易于理解。对我来说,最明显的问题是,如果不看
电影
的代码,150的含义就不明显了。如果您愿意,有几种方法可以改进:

  • 使用类型作为电影长度并构造该类型内联新电影长度(150)
  • 使用
  • (参见@Heinzi的答案)使用对象初始值设定项
  • 使用
  • 有了流畅的界面,您的通话看起来就像

     Movie m = new Movie("Inception").
       MadeIn(2010).
       InGenre(Genre.Drama).
       WithRuntimeLength(150).
       WithActors(actors);
    

    坦率地说,这一切对你的案子来说似乎都太过分了。如果您使用的是.NET 4.0,则命名参数是合理的,因为它们不是太多的代码,并且可以改进调用方的代码。

    我认为保留公共构造函数的方式没有什么错。以下是我在决定是否使用工厂方法时倾向于遵循的一些规则

    • 当初始化需要复杂的算法时,请使用工厂方法
    • 一定要使用工厂的m