Static factory methods vs Instance (normal) constructors?

前端 未结 11 1421
醉梦人生
醉梦人生 2020-12-02 12:16

In a language where both are available, would you prefer to see an instance constructor or a static method that returns an instance?

For example, if you\'re creating

相关标签:
11条回答
  • 2020-12-02 12:51

    It depends. For languages in which using an instance constructor is "normal", I would generally use one unless I had good reason not to. This follows the principle of least surprise.

    By the way, you forgot another common case: A null/default constructor paired with an initialization method.

    0 讨论(0)
  • 2020-12-02 12:55

    In Effective Java, 2nd edition, Joshua Bloch certainly recommends the former. There are a few reasons I can remember, and doubtless some I can't:

    • You can give the method a meaningful name. If you've got two ways of constructing an instance both of which take an int, but have different meanings for that int, using a normal method makes the calling code much more readable.
    • A corollary of the first - you can have different factory methods with the same parameter list
    • You can return null for "potentially expected failure" cases whereas a constructor will always either return a value or throw an exception
    • You can return a type other than the declared (e.g. return a derived class)
    • You can use it as a factory, to potentially return a reference to the same object several times

    The downsides:

    • It's not as idiomatic, currently - developers are more used to seeing "new"
    • If you see "new" you know you're getting a new instance (modulo the oddity I mentioned recently)
    • You need to make appropriate constructors available for subclasses
    • In C# 3, constructor calls are able to set fields/properties in a compact manner with object initializer expressions; the feature doesn't apply to static method calls
    0 讨论(0)
  • 2020-12-02 12:57

    I write a constructor when creating the instance has no side effects, i.e. when the only thing the constructor is doing is initializing properties. I write a static method (and make the constructor private) if creating the instance does something that you wouldn't ordinarily expect a constructor to do.

    For example:

    public class Foo
    {
       private Foo() { }
    
       private static List<Foo> FooList = new List<Foo>();
       public static Foo CreateFoo()
       {
          Foo f = new Foo();
          FooList.Add(f);
          return f;
       }
    }
    

    Because I adhere to this convention, if I see

    Foo f = Foo.CreateFoo();
    Bar b = new Bar();
    

    while reading my code, I have a very different set of expectations about what each of those two lines is doing. That code isn't telling me what it is that makes creating a Foo different from creating a Bar, but it's telling me that I need to look.

    0 讨论(0)
  • 2020-12-02 12:57

    There's a paper from ICSE'07 that studied the usability of constructors vs. factory patterns. While I prefer factory patterns, the study showed that developers were slower in finding the correct factory method.

    http://www.cs.cmu.edu/~NatProg/papers/Ellis2007FactoryUsability.pdf

    0 讨论(0)
  • 2020-12-02 12:58

    As Jon Skeet paraphrased Josh Bloch, there are a number of reasons why a static factory method is preferable to a constructor in many cases. I would say that if the class is a simple one with no expensive setup or complicated usage, stay with the idiomatic constructor. Modern JVMs make object creation extremely fast and cheap. If the class might be subclassed or you are able to make it immutable (a big advantage for concurrent programming, which is only going to get more important), then go with the factory method.

    One more tip. Don't name the factory method Foo.new* or Foo.create*. A method with these names should always return a new instance, and doing so misses one of the big advantages of the factory method. A better naming convention is Foo.of* or Foo.for*. The Google Guava library (formerly Google Collections Library) does a great job of this, imho.

    0 讨论(0)
提交回复
热议问题