What Are Static Factory Methods

What are static factory methods?

We avoid providing direct access to database connections because they're resource intensive. So we use a static factory method getDbConnection that creates a connection if we're below the limit. Otherwise, it tries to provide a "spare" connection, failing with an exception if there are none.

public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;

private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

private DbConnection(){
// ...
totalConnections++;
}

public static DbConnection getDbConnection(){

if(totalConnections < MAX_CONNS){
return new DbConnection();

}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;

}else {
throw new NoDbConnections();
}
}

public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}

Is it forbidden to use static methods in factory pattern?

The first thing to be 100% clear about is that there is no single "Factory Pattern". The term Factory describes a category of patterns with wildly differing implementations. When someone says Factory Pattern they could be talking about any creational pattern; but most commonly the phrase Factory Pattern indicates ignorance of design patterns.

Two very specific Factory Patterns are published in the famous Gang of Four book: Abstract Factory and Factory Method.

Static Factory was popularized by Joshua Bloch in Effective Java. There is no relationship between Bloch's Static Factory Method and the GoF's Factory Method, other than having similar names.

I will adjust the original question then, to provide a clear answer.

Is it forbidden to use static methods in the GoF Factory Method pattern?

Yes. The GoF pattern requires inheritance, which is not supported by static methods. This does not make the Static Factory pattern less useful! Static Factory is a perfectly legitimate design pattern that happens to be implemented in a very different way from the GoF Factory Method pattern. You may use both patterns when appropriate; and now you can label them appropriately as well.

Consider providing static factory methods insteads of constructors

This chapter from the book Effective Java explains it well: Consider Static Factory instead of Constructors. It explains all the pros and cons for both of them in the best way you can understand.

Just to quote the advantages and disadvantages from the book:

Advantages:

  • 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 (This one can be ignored in Java 7)

Disadvantages:

  • 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 can study them in more detail in the link I gave.

Static Factory method Advantages

I want to know how the API size is reduced by implementing this method and not having separate public classes.

Let's use the same concrete example used in the book: java.util.EnumSet has static factories that return one of two implementations: RegularEnumSet or JumboEnumSet. These implementations have their own complexities, but are effectively hidden to the clients of Collections. In theory, the factories could use other implementations in the future, and the clients of them would not be affected.

If you visualized this in a class diagram, the factory methods (e.g., of(), as opposed to a constructor) return an abstract type EnumSet, which hides the details of the implementations. Abstract (or Interface) types effectively abstract (simplify) the API.

Sample Image

What's more, the implementations are actually package private, meaning they're declared without a public keyword. This means that only classes in the same package can see them, so it prevents having Client depend on them. This is a great example of information hiding, which allows API developers to simplify their API and also to change the hidden parts later without breaking the code.

Another example that comes to mind where factory methods can simplify an API are the concrete iterators in Collections. In this case, it's a factory method that is not static, e.g., ArrayList.iterator(), that returns a concrete iterator for ArrayLists. The name of this class is even less "known" than the EnumSet implementations.

Static Factory Methods - return any subtype

1. Hiding from the client (better encapsulation) of object creation

Here's an example of a so-called "Simple Factory" (a.k.a. parametrized factory):

public class UserFactory {

public static User newUser(UserEnum type){
switch (type){
case ADMIN: return new Admin();
case STAFF: return new StaffMember();
case CLIENT: return new Client();
default:
throw new IllegalArgumentException("Unsupported user. You input: " + type);
}
}
}

The point of encapsulating object creation into a static factory is that the users don't know (and don't care) how an object gets created:

// client code - give me an admin object, 
// don't care about the inner details of how it gets constructed
User admin = UserFactory.newUser(ADMIN);

2. Flexibility to swap out implementations without breaking client code

Consider this static factory method:

// swap out with LinkedList later if you like, 
// it won't break the 100 places that invoke this method
public static List<String> getMyList(){
return new ArrayList<>();
}

Don't like any of the standard list implementations and you create your own some time later?

public class MyMuchBetterList<E> extends AbstractList<E> implements List<E> {

// implementation
}

No problem, you can still swap inside the static factory without affecting those using getMyList:

public static List<String> getMyList(){
return new MyMuchBetterList<>(); // compiles and works, subtype of list
}

Static factory methods with generics

There may be no perfect answer here. There are several options that could make sense, but the details may depend on the application case. I'll list some options regarding the questions of where should the static factory methods be, and what should be their names?


  1. Put them into the classes

This is what you have done now, but may have some caveats: The method in A creates an instance of A, and you cannot magically change this to be a B just by calling it "through" B. B.create() will still create an A, no matter what you do.

And creating a create() method in B will cause a name clash, as you observed.



  1. Put them into classes that correspond to the classes that they operate on

The approach that Tomasz Linkowski mentioned in his answer is not an uncommon practice: For classes that are called ClassName, there is a class called ClassNames that contains methods for creating instances.

It's so bugging me when the class name has no sensible plural, though...

As an example:

class Customer { /* With package-private constructor, usually ... */ }
public final class Customers {
public static Customer create() { ... }
}

class PremiumCustomer { /* With package-private constructor, usually ... */ }
public final class PremiumCustomers {
public static PremiumCustomer create() { ... }
}

This has the advantage that you can easily add classes that extend Customer, without affecting the existing codebase.

A minor drawback here is that you cannot use static imports of the methods, because they all have the same name, but that should rarely be an issue in real code.



  1. Put them into one class that aggregates the different types

Your classes are called A and B, which does not convey the actual structure. But depending on this structure, it may make more sense to have one class with different factory methods (with different names) that indicate the specializations:

public final class Customers {
public static Customer createStandard() { ... }
public static PremiumCustomer createPremium() { ... }
}

Which of the latter options is "better" is hard to say. It also depends on the package structure: When the classes are in different packages, you cannot make their constructors package-private, which may be undesirable.


A note that might be important: You specifically asked about static factory methods. But the scenario that you described raises another question: Who should call these methods, and how?

Everybody has to know the exact type of the instance that he wants to create...

In general, when there is polymorphism and inheritance involved, static methods always fall out and can cause headaches. You should consider using a ("simple", non-static) Factory instead.

When you have this:

void example() {
Customer customer = Customer.create();
doSomeComplexStuffWith(customer);
}

then the implementor has to explicitly call Customer.create() (or Customers.create() or Customers.createDefault() - this does not matter here).

Changing the type of the elements that are created there is not possible.

At these points, you could consider to change the use of the static factory method to that of a Supplier:

void example(Supplier<? extends Customer> supplier) {
Customer customer = supplier.get();
doSomeComplexStuffWith(customer);
}

This way, you can use the static methods as actual factory instances, probably as method references. The implementation of the example method is unaffected by changes of the type here:

example(Customers::createStandard); // Run example with standard customers
example(Customers::createPremium); // Run example with premium customers

But again, that depends on how you intend to create and use the instances in the first place.


A minor remark:

calling overridable methods in the constructor ... is strongly discouraged

This is true. But one could consider it as a corner case when you have a static factory method, and make the constructor of the class private or protected. Then, you can establish a contract and have far more control over the creation process, and make sure that there are no undesirable effects caused by the overridden method.

But in general, factories may indeed make it unnecessary to call overridable methods in constructor.

Static factory methods instead of constructors

but could not be implemented in the constructor itself?

No: new, by specification, always creates a new instance (or fails), so new Boolean(b) would always return a new instance of Boolean.

Boolean.valueOf returns a pre-existing instance. This is desirable, because there are only two possible values, so there is simply no point in creating more.



Related Topics



Leave a reply



Submit