Static factory methods

You’ve learned to create an object using new. However, there are classes in Java class libraries that cannot be instantiated this way. For example, you cannot create an instance of java.util.LocalDate with new because its constructor is private. Instead, you would use one of its static methods, such as now:

LocalDate today = LocalDate.now();

Such methods are called static factory methods.

You can design your class to use static factory methods. Listing 4.11 shows a class named Discount with a private constructor. It is a simple class that contains an int that represents a discount rate. The value is either 10 (for small customers) or 12 (for bigger customers). It has a getValue method, which returns the value, and two static factory methods, createSmallCustomerDiscount and createBigCustomerDiscount. Note that the static factory methods can invoke the private constructor to create an object because they are in the same class. Recall that you can access a class private member from within the class. With this design, you restrict a Discount object to contain either 10 or 12. Other values are not possible.

Listing 4.11: The Discount classs

package app04;
import java.time.LocalDate;

public class Discount {
    private int value;
    private Discount(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public static Discount createSmallCustomerDiscount() {
        return new Discount(10);
    }

    public static Discount createBigCustomerDiscount() {
        return new Discount(12);
    }
}

You can construct a Discount object by calling one of its static factory methods, for example

Discount discount = Discount.createBigCustomerDiscount();
System.out.println(discount.getValue());

There are also classes that allow you to create an instance through static factory methods and a constructor. In this case, the constructor must be public. Examples of such classes are java.lang.Integer and java.lang.Boolean.

With static factory methods, you can control what objects can be created out of your class, like you have seen in Discount. Also, you might cache an instance and return the same instance every time an instance is needed. Also, unlike constructors, you can name static factory methods to make clear what kind of object will be created.