Static factory vs Instance (normal) constructor methods?

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

For example, if you create a String from char[] :

  • String.FromCharacters(chars);

  • new String(chars);

+45
constructor coding-style design-patterns
Oct 11 '08 at 19:41
source share
11 answers

In Effective Java, 2nd Edition , Joshua Bloch certainly recommends the former. There are several reasons that I can recall, and undoubtedly some that I cannot:

  • You can give the method a meaningful name. If you have two ways of constructing an instance, each of which accepts an int, but has different meanings for this int, using the usual method makes the calling code a lot more readable.
  • Corollary of the first - you can have different factory methods with the same list of parameters
  • You can return zero for cases of "potentially expected failure", while the constructor will always either return a value or throw an exception
  • You can return a type different from the declared one (for example, return a derived class)
  • You can use it as a factory to potentially return a reference to the same object several times

Disadvantages:

  • It's not so idiomatic at the moment - developers are more used to seeing the β€œnew”
  • If you see β€œnew,” you know that you are getting a new instance (modulo the oddity I mentioned recently )
  • You must make the appropriate constructors available for subclasses.
  • In C # 3, constructor calls can compactly set fields / properties using object initializer expressions; function does not apply to static method calls
+53
Oct 11 '08 at 19:48
source share

I am writing a constructor when creating an instance without side effects, i.e. when the only thing the constructor does is initialize the properties. I am writing a static method (and making the constructor private) if instantiating does what you normally don't expect from the constructor.

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; } } 

Since I adhere to this agreement, 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 these two lines does. This code does not tell me what exactly makes creating Foo different than creating a bar, but it tells me what I need to see.

+21
Oct 11 '08 at 20:06
source share

If your object is immutable, you can use the static method to return cached objects and save memory allocation and processing.

+9
Oct 11 '08 at 20:05
source share

I recently worked on a public API, and I was tormented by choosing static factory methods and a constructor. Static factory methods definitely make sense in some cases, but in other cases this is not so clear, and I'm not sure if consistency with the rest of the API is reason enough to include them in constructors.

In any case, I came across a quote from an interview with Bill-Venners with Josh Bloch , which I found useful:

When you write a class, you can run my list of books on the benefits of static plants over public designers. If you find that a significant number of such advantages in the case, you should go with static factories. Otherwise, you should go to the constructors.

Some people were disappointed to find this advice in my book. They read it and said: "You argued so much for public static plants that we should use them by default." I The only real flaw in this means that it is a little embarrassing to people who are used to using constructors to create their objects. And I suppose this provides a bit less visual hint to the program. (You do not see a new keyword.) And it is a little more difficult to find static factories in the documentation, because Javadoc groups all the constructors together. But I would say that everyone should consider static time plants and use them when they are needed.

After reading this quote and the study that Uri * mentioned , I tend to err in favor of designers, unless there is a compelling reason to do otherwise. I think a static factory method without a good reason is probably just unnecessary complexity and over engineering. Although I could change my mind again tomorrow ...

* Unfortunately, this study focused less on static factory methods and more on the factory pattern (where there is a separate factory object for creating new instances), so I'm not sure that it can really be concluded that static factory methods confuse many programmers. Although the study gave me the impression that they often will.

+9
Jun 15 '11 at 10:59
source share

There was an article from ICSE'07 that examined the usability of constructors versus factory patterns. Although I prefer factory patterns, research has shown that developers were slower to find the right factory method.

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

+7
Oct 11 '08 at 19:54
source share

Static method. Then you can return null and not throw an exception (except for the reference type)

+2
Oct 11 '08 at 19:44
source share

I prefer the instance constructor only because it makes more sense to me, and there is less potential ambiguity with what you are trying to express (for example: what if FromCharacters is a method that takes a single character). Of course, subjective.

+2
Oct 11 '08 at 19:46
source share

I personally prefer to see a regular constructor, since constructors should be used for construction. However, if there are good reasons not to use it, that is, if FromCharacters explicitly stated that it does not allocate new memory, this would be useful. β€œNew” in the call makes sense.

+2
Oct 11 '08 at 19:48
source share

It depends. For languages ​​in which using the instance constructor is β€œnormal”, I would usually use it if I had no good reason. This follows the principle of least surprise.

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

+2
Oct 11 '08 at 20:08
source share

As John Skeet Josh Bloch has rephrased, 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 simple, without expensive installation or complex use, stay with the idiomatic constructor. Modern JVMs make creating objects extremely fast and cheap. If a class can be subclassed or you can make it immutable (a big advantage for parallel programming, which will only become more important), then use the factory method.

One more tip. Not Foo.new* factory method Foo.new* or Foo.create* . A method with these names should always return a new instance, and one of the big advantages of the factory method is missed. The best naming convention is Foo.of* or Foo.for* . The Google Guava Library (formerly the Google Collection Library) does an excellent job of this, imho.

+1
Oct. 12 '08 at 5:03
source share

Of course, there are several advantages of static factory methods over constructors.

  1. Factory methods help us write flexible code. While the designers made it closely related.
  2. Static factory methods improve readability because they allow you to create different instances.
  3. You can return the cached object. For example, getInstance() in a singleton.
0
Jan 28 '19 at 17:31
source share



All Articles