Factory Pattern in Java
In Appendix G2's OrderManager, the code that uses a discount also decides which discount to apply, through a chain of if statements on "GOLD", "SILVER" and "STAFF". Every place that needs a discount repeats that decision. The Factory pattern moves the decision into one place: callers ask for "the right discount for this customer" and get back an object of the interface type, without knowing or caring which class it is.
A Discount Factory
public class Factories {
enum CustomerType { GOLD, SILVER, STAFF, REGULAR }
interface DiscountPolicy {
long apply(long amount);
String label();
}
record PercentOff(int percent, String label) implements DiscountPolicy {
public long apply(long amount) {
return amount * (100 - percent) / 100;
}
}
static final class DiscountFactory {
private DiscountFactory() { }
static DiscountPolicy forCustomer(CustomerType type) {
return switch (type) {
case GOLD -> new PercentOff(20, "Gold 20%");
case SILVER -> new PercentOff(10, "Silver 10%");
case STAFF -> new PercentOff(50, "Staff 50%");
case REGULAR -> new PercentOff(0, "No discount");
};
}
}
public static void main(String[] args) {
long bill = 4000;
String[] customers =
{"Navika:GOLD", "Srihitha:REGULAR", "Advitha:STAFF"};
for (String c : customers) {
String[] parts = c.split(":");
DiscountPolicy policy =
DiscountFactory.forCustomer(CustomerType.valueOf(parts[1]));
System.out.println(parts[0] + " (" + policy.label() + "): Rs. "
+ policy.apply(bill));
}
}
}Navika (Gold 20%): Rs. 3200
Srihitha (No discount): Rs. 4000
Advitha (Staff 50%): Rs. 2000How it works
DiscountFactory.forCustomer(type)is the only place that maps a customer type to a discount.- It returns the interface type,
DiscountPolicy.mainnever writesnew PercentOff(...). - The decision is a
switchover an enum, so the compiler checks every customer type is handled; a new type that's forgotten is a compile error. - To change Gold to 25%, or to return a completely different class for staff, you edit the factory only.
Static Factory Methods
The simplest kind of factory is a static method on the class itself that returns an instance, in place of a public constructor:
| JDK example | What it gives you over new |
|---|---|
Integer.valueOf(42) | Can return a cached object |
List.of("a", "b") | Can return a hidden class chosen for the size |
LocalDate.of(2026, 1, 26) | A descriptive name, and validation |
Optional.empty() | A shared single instance |
EnumSet.noneOf(Day.class) | Picks a different implementation depending on the enum's size |
Advantages over constructors: factories have names (ofWeek, fromCsv), can reuse objects, can return subtypes, and can validate before creating anything.
Common Mistakes
Factories that return concrete types. Return the interface, or callers end up depending on the class anyway.
Spreading the "which class?" decision around. If the same if-else on a type appears in several places, collect it into one factory.
Factories for classes with only one implementation and nothing to decide. A constructor is fine.
Interview Corner
What is the factory pattern, and why use it?
A factory is an object or method responsible for creating other objects, deciding which concrete class to instantiate and returning it through an interface or base type. It centralizes creation logic, hides implementation classes from callers, makes it easy to add or change implementations in one place, and allows caching or validation. Static factory methods such as List.of and Integer.valueOf are the simplest form.
What are the advantages of static factory methods over constructors?
They have descriptive names, they aren't required to create a new object on each call, they can return any subtype of their declared return type, and they can choose the returned class based on the arguments.
Practice
- Easy: Add a
PLATINUMcustomer type with 30% off. Which code did you change? - Harder: Write a
NotifierFactory.forChannel(String channel)that returns an SMS, email or app notifier implementing aNotifierinterface, and throwsIllegalArgumentExceptionfor unknown channels.
Key Takeaways
Was this tutorial helpful?