一个C#类是否应该生成自身的实例?

13

我有一个定义了CallRate类型的类。我需要通过从文件中读取数据来添加创建多个类实例的能力。

我向CallRate类中添加了一个静态方法,该方法返回一个List<CallRate>。一个类通过调用自己的构造函数来生成新实例是否可以?它可以工作,但我想知道这是否是正确的做法。

List<CallRates> cr = CallRates.ProcessCallsFile(file);
12个回答

20

从静态方法中获取其自身的对象是完全可以的。

例如:

其中一个.NET库做了与您所做的相同的事情。

XmlReadrer reader = XmlReader.Create(filepathString);

如果我没记错的话,这被称为工厂模式,并且正如所述,是一种完全可行的完成任务的方法。我通常更喜欢将工厂与类分开,但这在很大程度上取决于个人偏好。 - Matthew Brubaker
在GoF书中有两种工厂:抽象工厂和工厂方法。所提供的方法是工厂方法的一个例子。 - Cyber Oliveira
是的,工厂模式确实。 - Ray Lu

5

3

当我需要检查参数的有效性时,我经常使用这种模式。强烈不建议从构造函数中抛出异常。从工厂方法中抛出也不是很糟糕,或者您可以选择返回null。


2

对我来说看起来很好。在其他语言中,您可能会编写一个函数,但在像C#这样的语言中,静态方法承担了该角色。


1

工厂方法通常是一个很好的设计。当我在C#中编写它们时,我称之为“New”,这样做的原因是:

new MyClass()

变成

MyClass.New()

这个实现非常简单:

class MyClass
{
    public static MyClass New()
    {
        return new MyClass();
    }
}

通常情况下,我这样做是因为有其他条件来判断是否要创建类或者只是返回null,或者是返回MyClass或者它的派生类。


对于那些习惯了VB.Net的人来说,这可能会很困惑。在VB.Net中,构造函数被称为"New"。 - Kibbee
也许吧;或者说这样想,它就像是静态构造函数和实例构造函数之间的区别。我不能确定,因为我没有花太多时间与VB.NET程序员在一起。 - Jay Bazuzi

1

通常我在需要一个类的即时实现时使用它。例如

    public class Car
    {
        public static Car RedExpensiveCar = new Car("Red", 250000);

        public Car()
        {

        }

        public Car(string color, int price)
        {
            Color = color;
            Price = price;
        }

        public string Color { get; set; }
        public int Price { get; set; }
    }

有了这个,我就不需要在代码中记住或写构造函数参数了。

Car car = Car.RedExpensiveCar;

请注意,在您的示例中,Car car = Car.RedExpensiveCar 不会 创建新的Car对象。它将始终返回同一实例。更麻烦的是,由于您正在使用公共字段,因此它可能会被重新赋值为:Car.RedExpensiveCar = new Car("Primer Brown", 75)。 - munificent
通常情况下,更好的做法是公共静态汽车RedExpensiveCar { get { return new Car("红色", 250000); } }。 - munificent

1

没问题。你刚刚创建的东西有点像一个简单的工厂方法。你有一个静态方法来创建一个有效的类型实例。实际上,你的方法甚至不需要是静态的,你仍然有一个有效的代码。有一种设计模式(原型)可以从现有对象创建一个新的有效对象。详见http://www.dofactory.com/Patterns/PatternPrototype.aspx


我需要一个好的理由来开始学习类设计模式。谢谢。 - user10178

1

当涉及到简单的解析(或类似)场景时,我实际上更喜欢工厂方法是类的一部分。是的-它确实破坏了SRP,但它实现了KISS-所以我认为这是一个净胜利。对于更大的应用程序或更复杂的解析例程,将其作为外部工厂类更有意义。

对于您的特定情况,我可能更喜欢采用接受IEnumerable<string>而不是文件名的方法-这仍然可以给您提供解析逻辑,但允许轻松进行单元测试和“重用”。调用者可以轻松地将文件包装成IEnumerable。


1

有时我会使用公共静态方法作为构造函数重载的替代方案。

特别是在不依赖参数类型来指示所需对象构造类型的情况下。


1

我喜欢使用静态方法返回实例,正如上面多次建议的那样。

@Paul:不要忘记勾选上面的评论,你会发现它是最佳答案。


抱歉!大家都帮了我,所以我给了所有人点赞。我没有声望通过打钩向下移除,只选择一个。boneHead = 我; - user10178
通过第二次按下“上标”来取消它们。 - Bjarke Ebert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接