Provide Java class clients with static factory methods, not constructors

In this post, we look at the advantages, and disadvantages, of using static factory methods.

The advantages of using static factory methods, over using public constructors, significantly outnumber the disadvantages, and for this reason alone any Java programmer should have this technique in their quiver.

Summary

A static factory method is a static method that returns an instance of its class that may or may not have its constructors marked private.

The advantages and disadvantages of using static factory methods are listed below.

Advantages

  1. They can have descriptive names, unlike constructors.
  2. They do not have to create a new object each time they are invoked, unlike constructors.
  3. They can return an object of any subtype of their return type, unlike constructors.
  4. They reduce the verbosity of creating parameterized type instance (this hold for Java 5 & 6, not Java 7).
  5. They can be used to prevent the this reference escaping during construction.

Disadvantages

  1. Classes without public or protected constructors cannot be subclassed.
  2. They are not readily distinguishable from other static methods.

Digging Deeper

Advantage: They can have descriptive names, unlike constructors

The parameters of a public constructor may not provide an apt description of the object being returned, however with a static factory method one can choose a suitable descriptive name making the resultant client code much more readible and comprehensible.

In addition to the above, it is worth noting that with public constructors, you can only have a single constructor with a given signature, however, thanks to method overloading, two or more contructors with the same signature, that differ in terms of their behaviour, can share the same signature.

Advantage: They do not have to create a new object each time they are invoked, unlike constructors

If the class in question is immutable, then the class in question can be instance controlled. With this, static factory methods return preconstructed instances or cache instances as they are constructed and return these repeatedly instead of wasting resources by needlessly returning duplicate objects. Singletons, representing unique components, are instance controlled.

Advantage: They can return an object of any subtype of their return type, unlike constructors

With this, interface-based frameworks can be created, where interfaces serve as the return types for static factory methods. This leads to clean, simple APIs where implementation classes are hidden, as they should be.

A good example of the aforementioned technique is the Java Platform’s Collections class.  Notice how for example the synchronizedList static contructor returns interface type List.

Advantage: They can reduce the verbosity of creating parameterized type instances in Java 5 & 6 (not 7)

In Java 5 and 6, should you wish to create a paremerized type instance using a contructor, you would have to, for example, do the following:

List<String> names = new ArrayList<String>();

With a static factory method, one can do the following, thanks to type inference, which is far more compact:

List<String> names = ArrayList.newInstance();

The above assumes the following static factory method:

public static <V> ArrayList<V> newInstance() {

return new ArrayList<V>();

}

With Java 7, the cited advantage of static factory methods is lost since with Java 7’s  support for type inference for generic instance creation, you can do the following:

Map<String, List<String>> myMap = new HashMap<>();

Advantage: They can be used to prevent the this reference escaping during construction

In Java Concurrency in Practice, Goetz et. al. advise readers to prevent having the this reference escape during construction to avoid the situation where a thread is able to see an owning object before it is fully constructed. Registering an event listener or starting a thread from a constructor are said to be prime examples of how one can inadvertantly, and unsafely, publish the this reference. In order to avoid improper construction when registering an event listener or starting a thread from a constructor, all one has to do is to use a private constructor and a public factory method.

// The reference for this example is Section 3.2.1 Safe Construction Practices in 
// Java Concurrency in Action 
public class ThisRefNotEsc {
	private final EventListener listener;
	
	private ThisRefNotEsc() {
		listener = new EventListener() {
			public void onEvent(Event e) {
				processEvent(e);
			}
		}
	}	
	
	public static ThisRefNotEsc newInstance(EventSource eventSource) {
		ThisRefNotEsc safelyConstructed = new ThisRefNotEsc();
		eventSource.registerListener(safelyConstructed.listener);
		return safelyConstructed;
	}
}

Disadvantage: Classes without public or protected constructors cannot be subclassed

This disadvantage holds only when one wants to use inheritance, as opposed to composition.

Disadvantage: They are not readily distinguishable from other static methods

Using established naming conventions offer a workaround to this disadvantage. For example, using newInstance or getInstance, amongst other conventional names.

References

Effective Java, Second Edition, Joshua Bloch: Item 1: Consider static factory methods instead of constructors.

What are static factory methods in Java? Stackoverflow

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s