javaoopinterfaceinstantiationstatic-constructor

Is it better practice to use static factory methods over an interface implemented by many different objects?


It seems as though you could either use static factory methods or you can use an interface that many objects implement to make it easier for users (or yourself) to instantiate the correct object.

Therefore, it seems to be a decision between, on the one hand, having giant objects with many static factory methods or on the other hand, having an interface that many different objects implement, so many so it would becomes hard for the user to know where to even start.

Example 2: A class with many static factory methods:

FooObj foo01 = FooObj.bigFoo();
FooObj foo02 = FooObj.smallFoo();

Example 1: An interface with many classes that implement the interface.

Foo foo1 = new BigFoo();
Foo foo2 = new SmallFoo();

Solution

  • The question which you are thinking is answered in the famous book. Effective Java, 3rd Edition by Joshua Bloch. Note that Joshua Bloch is also developer of multiple Java SE classes as well.

    Quoting from the book:

    ITEM 1: CONSIDER STATIC FACTORY METHODS INSTEAD OF CONSTRUCTORS

    Joshua gives following reasons for using static factory method in place of the constructors

    • 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 factories is that the class of the returned object can vary from call to call as a function of the input parameters.
    • A fifth advantage of static factories is that the class of the returned object need not exist when the class containing the method is written.

    Joshua also tells problems with the static factory methods

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

    • A second shortcoming of static factory methods is that they are hard for programmers to find.

    Java.util.Collections can be seen as an example for static factory method. Quoting from the book

    For example, the Java Collections Framework has forty-five utility implementations of its interfaces, providing unmodifiable collections, synchronized collections, and the like. Nearly all of these implementations are exported via static factory methods in one noninstantiable class (java.util.Collections). The classes of the returned objects are all nonpublic.

    Further the author echoes your thoughts

    The Collections Framework API is much smaller than it would have been had it exported forty-five separate public classes, one for each convenience implementation. It is not just the bulk of the API that is reduced but the conceptual weight: the number and difficulty of the concepts that programmers must master in order to use the API. The programmer knows that the returned object has precisely the API specified by its interface, so there is no need to read additional class documentation for the implementation class. Furthermore, using such a static factory method requires the client to refer to the returned object by interface rather than implementation class, which is generally good practice (Item 64).

    Java Standard Library makes extensive use of the static factory method because of the advantages suggested by Joshua Bloch. Another example is the valueOf function in the java.lang.Boolean class. The valueOf static factory method beautifully provide you the same object again and again (basically caching)

    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);
    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }