117. Template Method vs Strategy Pattern
Template Method uses inheritance to fix an algorithm skeleton with abstract hook steps; Strategy uses composition and functional interfaces to swap interchangeable algorithms at runtime.
Java 21 (Modern idiomatic patterns)Explanation
Both Template Method and Strategy solve algorithm customization, but their structural mechanisms represent the classic OOP tradeoff: Inheritance vs Composition.
- Template Method (Inheritance): Defines the invariant skeleton of an algorithm in a final superclass method. Subclasses implement or override protected primitive/hook methods. - *Tradeoff*: Simple to write when subclassing is natural; but couples subclasses tightly to the base class, limits flexibility because Java does not support multiple class inheritance, and algorithm logic cannot be swapped dynamically at runtime on an existing object. - Strategy Pattern (Composition): Encapsulates the algorithm into a separate strategy interface. The context class holds a reference to the strategy and delegates work to it. - *Modern Java advantage*: In modern Java, Strategy shines because strategies can be expressed as single-method functional interfaces (Predicate, Comparator, custom @FunctionalInterface), allowing callers to supply strategies on the fly using concise lambdas or method references without declaring subclass boilerplate!
Example
import java.util.List;
import java.util.function.UnaryOperator;
public class TemplateVsStrategy {
// 1. STRATEGY PATTERN (Modern Java with lambdas)
@FunctionalInterface
interface DiscountStrategy {
double applyDiscount(double originalPrice);
}
public static class ShoppingCart {
public double calculateTotal(List<Double> items, DiscountStrategy discount) {
double total = items.stream().mapToDouble(Double::doubleValue).sum();
return discount.applyDiscount(total); // Delegates to strategy
}
}
// 2. TEMPLATE METHOD PATTERN (Inheritance)
public static abstract class ReportGenerator {
// Final skeleton method โ steps cannot be bypassed
public final void generate() {
fetchData();
formatContent();
export();
}
protected abstract void fetchData();
protected abstract void formatContent();
protected void export() {
System.out.println("Exporting report to standard console.");
}
}
public static void main(String[] args) {
// Strategy allows instant switching via lambdas:
ShoppingCart cart = new ShoppingCart();
List<Double> items = List.of(50.0, 50.0);
double standard = cart.calculateTotal(items, price -> price);
double vipSale = cart.calculateTotal(items, price -> price * 0.80);
System.out.printf("Standard: $%.2f | VIP: $%.2f%n", standard, vipSale);
}
}Sources
- https://dev.java/learn/design-patterns/strategy/ โ dev.java Strategy Pattern
- https://en.wikipedia.org/wiki/Template_method_pattern โ Template Method Pattern