Stop Memorizing Design Patterns: Modern Strategy Pattern with Java 21+ Sealed Interfaces and Pattern Matching
The article critiques the classic interface‑plus‑N‑implementations Strategy Pattern for causing class explosion, then demonstrates how Java 17’s sealed interfaces and records together with Java 21’s pattern‑matching switch provide a more concise, type‑safe, and maintainable modern implementation.
Why the classic Strategy Pattern feels like a "file factory"
Traditional implementations use an interface with many concrete classes, leading to class explosion, high modification cost, scattered logic, and reduced readability as the number of strategies grows.
Traditional Java 7/8 implementation
public interface PaymentStrategy { void pay(double amount); }</code><code>public class CreditCardPayment implements PaymentStrategy { @Override public void pay(double amount) { System.out.println("Paid " + amount + " using Credit Card"); } }</code><code>public class PayPalPayment implements PaymentStrategy { @Override public void pay(double amount) { System.out.println("Paid " + amount + " using PayPal"); } }</code><pre><code>public class PaymentService { private PaymentStrategy strategy; public PaymentService(PaymentStrategy strategy) { this.strategy = strategy; } public void process(double amount) { strategy.pay(amount); } }Issues: class explosion, high change cost, dispersed logic, and readability decline.
Java 8 lambda shortcut (still limited)
PaymentStrategy creditCard = amount -> System.out.println("Paid " + amount + " using Credit Card");</code><code>PaymentStrategy paypal = amount -> System.out.println("Paid " + amount + " using PayPal");Reduces files but lacks type constraints, makes complex logic hard to maintain, and limits extensibility.
Java 17 sealed interfaces + records
Sealed interfaces restrict the set of permitted strategy types, while records express the data shape.
public sealed interface PaymentStrategy permits CreditCard, PayPal {}</code><code>public record CreditCard(String cardNumber) implements PaymentStrategy {}</code><code>public record PayPal(String email) implements PaymentStrategy {}Now a strategy combines data and type, eliminating the need for separate implementation classes.
Java 21 pattern‑matching switch
public class PaymentProcessor { public static void process(PaymentStrategy strategy, double amount) { switch (strategy) { case CreditCard cc -> System.out.println("Paid " + amount + " with card: " + cc.cardNumber()); case PayPal pp -> System.out.println("Paid " + amount + " via PayPal: " + pp.email()); } } }Benefits:
No need for N separate classes; all logic lives in a single, controllable switch.
Compile‑time type safety guarantees exhaustive handling.
Linear, readable code structure.
Reframing the Strategy Pattern
At runtime, choose different logic paths.
The modern approach treats the pattern as branch control rather than a polymorphic class hierarchy.
public static void process(PaymentStrategy strategy, double amount) { switch (strategy) { case CreditCard cc -> handleCard(cc, amount); case PayPal pp -> handlePayPal(pp, amount); } }Compared with the old style, it reduces class jumps, lowers mental overhead, and adds compile‑time validation.
When to use the modern strategy
Suitable scenarios:
Limited number of strategies (e.g., payment methods, order states).
Logic that benefits from centralized management.
Strong type constraints are important.
Unsuitable scenarios:
Highly dynamic strategies requiring plugin‑style extensibility.
Uncontrolled third‑party extensions.
Conclusion
The Strategy Pattern itself never changes; Java evolves. From class explosion to functional lambdas, and now to type‑driven pattern matching, the pattern has become a language capability. Mastery means knowing when to replace classic implementations with these modern constructs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
LuTiao Programming
LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
