Java Programming Tutorials

Java programming tutorials with many code examples!

Static Factory Method pattern

Static Factory Method is very popular pattern that simplify and clarify creation of objects. Can be used instead of or in addition to constructors.

Like everything else, Static Factory Methods have their pros and cons. Therefore we’ll go through them with concrete examples.

Name that clarifies intent

Good names makes the code easier to understand, hence less error prone and therefore faster to develop. I like to code fast. :-) Intention revealing name is one of those small ingredients of clean code that speed up development.

For example we’ve got the following class that can be instantiated from the given string, which is expected to be a date in ISO format:

public class MyDate {
    public MyDate(String isoDate) {
        //... parses given ISO Date
    }
}

It’s used in a system in the following way:

// Before use somebody will need to check javadoc
// to find what format is expected:
MyDate date = new MyDate("2/24/2017");

It is not immediately obvious in what format the string should be. We can introduce a static factory method to clarify that:

public class MyDate {
    private MyDate(String isoDate) {
        //... parses given ISO Date
    }

    public static MyDate fromISODate(String isoDate) {
        return new MyDate(isoDate);
    }
}

Now the expected string format is obvious:

MyDate date = MyDate.fromISODate("2017-02-24");

Of course the solution is not perfect, but at least it tells us what it expects and gives us a chance to spot an error, when a date parameter is in a different format.

Doesn’t have to create new objects every time

This is the result of separation of instantiation and a place it is used. As a matter of fact it is the property of all creational patterns. The classic example is in java.lang.Boolean, which just returns constants:

public Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

Also cached values could be returned.

In fact it’s common use case in JDK classes (for example see Collections.emptyList()).

Can return any subtype of return type

This benefit is clearly visible when using various libraries that leverage Service Provider Framework. We can program against an API and at run-time use different versions of libraries. This reduces conceptual weight of an API.

Example: To instantiate a Validator from Bean Validation we call Validation.buildDefaultValidatorFactory() static factory method. It will return registered implementation of ValidatorFactory, which can be either Hibernate Validator or Apache BVal:

// Call static factory method to get registered implementation:
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();

Another example is a bunch of static factory methods for different implementations of standard Java collections – synchronized List, unmofidiable List, etc.(see Java Collections).

Reduce verbosity of instantiation with initialization

A common case is to create a simple, static mapping in a class:

public Actions {
    private static Map<String,Action> actions = HashMap<>();
    static {
        actions.put("weight", new WeightMeasuer());
        actions.put("hight", new HeightMeasure());
    }
}

The map may be static or not, but the point is that we create such mapping only once. The initialization is verbose and split into two parts, which prevents use of immutable objects. This can be easily improved with a static factory method:

public Actions {
    // from Google Guava:
    private static Map<String,Action> actions
        = ImmutableMap.of("weight", new WeightMeasuer(),
                          "height", new HeightMeasure());
}

Now instantiation is less verbose and we can use an immutable object.

Harder to distinguish from other static methods

In case when a class has many static methods, static factory methods may be harder to distinguish from others. In such case using consistent naming convention somewhat helps. Usually static factory methods use these prefixes: new, of, valueOf, from.

This is not always a problem, but may manifest itself especially in Utils classes so popular in enterprise level software. ;-)

They don’t scale to large number of optional parameters

Just like constructors, they don’t scale. When we need to pass many parameters just to create an object, then we should consider if the object is cohesive and if so consider using the Builder Pattern.

Make testing harder

Use Static Factory Methods (and any static method in general) when initialization is simple and doesn’t involve further collaborators or external resources. Always think: “How am I going to test it?“. External dependencies (database, files, etc.) make things much more complicated.

Share with the World!