Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static factory methods vs Instance (normal) constructors?

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 a String from a char[]:

  1. String.FromCharacters(chars);

  2. new String(chars);

like image 518
Dan Goldstein Avatar asked Oct 11 '08 19:10

Dan Goldstein


People also ask

What is the difference between static constructor and instance constructor?

Static constructors allow you to initialize static variables in a class, or do other things needed to do in a class after it's first referenced in your code. They are called only once each time your program runs. Instance constructors are the ones that are called whenever you create new objects (instances of classes).

What is the benefit to use static factory in place of constructor?

Static factory methods can encapsulate all the logic required for pre-constructing fully initialized instances, so they can be used for moving this additional logic out of constructors. This prevents constructors from performing further tasks, others than just initializing fields.

What is the disadvantage of using static factory method instead of constructors while implementing the Factory pattern?

The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.

Why would one use the factory method rather than just using a constructor?

The factory method is a smart way to create objects in Java and provides several advantages over the traditional approach of creating objects using constructors in Java. It can also improve the quality of code by making the code more readable, less coupled, and improves performance by caching.


2 Answers

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
like image 199
Jon Skeet Avatar answered Sep 23 '22 13:09

Jon Skeet


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.

like image 41
Robert Rossney Avatar answered Sep 23 '22 13:09

Robert Rossney