When to use a Constructor and when to use getInstance() method (static factory methods)?
Everybody seems to focus on singletons while I think that the question is actually about constructor vs static factory methods.
This is actually Item 1: Consider static factory methods instead of constructors of Effective Java by Joshua Bloch:
Item 1: Consider static factory methods instead of constructors
The normal way for a class to allow a client to obtain an instance of itself is to provide a public constructor. There is another technique that should be a part of every programmer’s toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here’s a simple example from
Boolean
(the boxed primitive class for the primitive typeboolean
). This method translates a boolean primitive value into aBoolean
object reference:public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
Note that a static factory method is not the same as the Factory Method pattern from Design Patterns [Gamma95, p. 107]. The static factory method described in this item has no direct equivalent in Design Patterns.
A class can provide its clients with static factory methods instead of, or in addition to, constructors. Providing a static factory method instead of a public constructor has both advantages and disadvantages.
Advantages (quoting the book):
- One advantage of static factory methods is that, unlike constructors, they have names.
- A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.
- A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
- A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances.
Disadvantages (still quoting the book):
- The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.
- A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.
You've got two questions: when should I call a getInstance()
method, and when should I create one?
If you're deciding whether to call a getInstance()
method, it's easy. You just need to read the class documentation to find out when you should call it. For example, NumberFormat
provides a constructor and a getInstance()
method; the getInstance()
method will give you a localized NumberFormat
. For Calendar
, on the other hand, the constructor is protected. You have to call getInstance()
to get one.
If you're deciding whether to create a getInstance()
method, you need to decide what you're trying to accomplish. Either you don't want people to call your constructor (you're creating a singleton or a factory), or you don't mind (as in NumberFormat
above, where they're initializing some objects for the convenience of the caller).
Long story short? Don't worry about creating getInstance()
methods in your own code. If the time arises when they'll be useful, you'll know. And in general, if you can call a class's constructor, you're probably supposed to be doing that, even if the class provides a getInstance()
method.
The uses for getInstance methods:
- If you want to control/restrict construction e.g. Singleton
- implement Factory pattern, e.g. DriverManager.getConnection
- When you want to provide better name as to how the instance is constructed (constructors must have the same name as the class name), checkout the NumberFormat factory methods getCurrencyInstance, getIntegerInstance and others as examples of this.
But most of the time your object will be a simple POJO and usage of public constructors is most practical and obvious solution.
U1: getInstance From Another Class
To return an instance of a different class:
public class FooFactory {
public static Foo getInstance() {
return new Foo();
}
}
NumberFormat.getInstance
methods do this as they actually return instances of DecimalFormat
.
U2: Singleton Problems
The singleton pattern restricts many of the benefits of object oriented programming. Singletons generally have private constructors, therefore you cannot extend them. As you will be accessing it via its getInstance method and not referencing any interface, you will not be able to swap it out for another implementation.