Factory and Strategy Patterns
How to pass behaviour in as a parameter and centralise the decision of which implementation to build.
Open this lesson in the learning hubKey points
- Strategy: pass the algorithm in as an object. The caller picks the behaviour; the surrounding class never changes.
- In modern Java a strategy is usually just a lambda against a functional interface. No class explosion required.
Comparator,PredicateandFunctionare strategies the JDK already ships for you.- Factory: one place decides which implementation to create, so callers only ever depend on the interface.
- Static factory methods beat
newfor naming, caching and returning subtypes. SeeList.ofandOptional.of. - A registry
Mapfrom key to supplier turns an ever-growing switch into data you can extend.
Example
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class Main {
// STRATEGY: the algorithm is just another parameter.
interface Discount { double apply(double amount); }
static double checkout(double amount, Discount discount) {
return discount.apply(amount);
}
// FACTORY: one place decides which implementation the caller gets.
interface Notifier { String send(String msg); }
static final Map<String, Supplier<Notifier>> REGISTRY = Map.of(
"email", () -> msg -> "email -> " + msg,
"sms", () -> msg -> "sms -> " + msg
);
static Notifier notifierFor(String channel) {
Supplier<Notifier> factory = REGISTRY.get(channel);
if (factory == null) throw new IllegalArgumentException("unknown channel: " + channel);
return factory.get();
}
public static void main(String[] args) {
System.out.println(checkout(100, amount -> amount)); // no discount
System.out.println(checkout(100, amount -> amount * 0.9)); // 10% off
System.out.println(checkout(100, amount -> amount - 15)); // flat 15
System.out.println(notifierFor("email").send("build is green"));
System.out.println(notifierFor("sms").send("build is green"));
// Comparator is the JDK's own Strategy interface.
List<String> names = new ArrayList<>(List.of("Bea", "Al", "Cyd"));
names.sort(Comparator.comparingInt(String::length));
System.out.println(names);
}
}
Strategy swaps the how; factory hides the which.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.