Factory Method Pattern
What is The Factory Method Pattern?
The factory pattern is a pattern used for obtaining instances through a method instead of creating an instance using a constructor. When creating objects through their constructor, you don't have any control over them. With simple objects that just store data, this is usually what you would want. In other cases, such as instances where you have polymorphism, you are going to want to control the instances. This is where the factory pattern comes in.
Implementing The Factory Pattern
One use of a factory is constructing complex objects that require other dependencies.
// Java code
public final class ServiceFactory {
public final AccountService accountService = new AccountService();
public UserService userService() {
final var userService = new UserService();
userService.setAccountService(accountService);
return userService;
}
}
You can construct an object, wire up all of its dependencies, and then return it. This allows you to cache or create each dependency, depending on the use case.
Another use of a factory is returning instances using polymorphism. You can determine what instance to return depending on some type of state.
// Java code
public interface User {
String description();
}
public final class AdminUser implements User {
@Override
public String description() {
return "Administrator";
}
}
public final class ContentCreator implements User {
@Override
public String description() {
return "Content Creator";
}
}
public final class Consumer implements User {
@Override
public String description() {
return "Consumer";
}
}
public final class UserFactory {
public User build(final Account account) {
if (account.isAdmin()) {
return new AdminUser();
} else if (account.isContentCreator()) {
return new ContentCreator();
} else {
return new Consumer();
}
}
}
Another benefit of factories is that they can increase the testability of your code. You can mock the factory, stub the method that is being invoked, and return the object you need for your test.
Static Method Factories
A static factory is a static method on a class that returns instances of that class. The class commonly has a private constructor, so instances are obtained via the static factory method. Static factories are nice when your object is self-contained and only dependent on itself.
Singleton classes and caching can be done using a static factory method with the following:
// Java code
public final class Environment {
private static final Environment INSTANCE = new Environment();
public static Environment instance() {
return INSTANCE;
}
}
If you have a set number of instances, you can keep those in memory, calculate the instance, and return a constant.
// Java code
public final class Month {
private static final Month JAN = new Month();
private static final Month FEB = new Month();
private static final Month MAR = new Month();
private static final Month APR = new Month();
private static final Month MAY = new Month();
private static final Month JUN = new Month();
private static final Month JUL = new Month();
private static final Month AUG = new Month();
private static final Month SEP = new Month();
private static final Month OCT = new Month();
private static final Month NOV = new Month();
private static final Month DEC = new Month();
public static Month instance(final int month) {
return switch (month) {
case 1 -> JAN;
case 2 -> FEB;
case 3 -> MAR;
case 4 -> APR;
case 5 -> MAY;
case 6 -> JUN;
case 7 -> JUL;
case 8 -> AUG;
case 9 -> SEP;
case 10 -> OCT;
case 11 -> NOV;
case 12 -> DEC;
default -> throw new RuntimeException("...");
}
}
// ...
}
Depending on the features of the language you are using, this particular case would be better as an enumeration.
Static factories can also help clean up your API (Application Programming Interface) and add clarity when a class has multiple constructors.
Conclusion
Factories are one of the most powerful patterns. It can make the API clearer for developers, control object instances, and increase testability.