Strategy
Define family of algorithms and make them interchangeable
Overview
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.
This pattern is useful when you have multiple ways to do something and want to switch between them easily.
Key Concepts
Encapsulate algorithms in separate classes
Make algorithms interchangeable
Client chooses which algorithm to use
Avoids conditional statements
Follows Open/Closed Principle
Code Example
1// Strategy interface
2interface PaymentStrategy {
3 void pay(double amount);
4 boolean validate();
5}
6
7// Concrete strategies
8class CreditCardPayment implements PaymentStrategy {
9 private String cardNumber;
10 private String cvv;
11 private String expiryDate;
12
13 public CreditCardPayment(String cardNumber, String cvv, String expiryDate) {
14 this.cardNumber = cardNumber;
15 this.cvv = cvv;
16 this.expiryDate = expiryDate;
17 }
18
19 @Override
20 public boolean validate() {
21 System.out.println("Validating credit card...");
22 return cardNumber != null && cardNumber.length() == 16;
23 }
24
25 @Override
26 public void pay(double amount) {
27 System.out.println("Paid $" + amount + " using Credit Card");
28 }
29}
30
31class PayPalPayment implements PaymentStrategy {
32 private String email;
33 private String password;
34
35 public PayPalPayment(String email, String password) {
36 this.email = email;
37 this.password = password;
38 }
39
40 @Override
41 public boolean validate() {
42 System.out.println("Validating PayPal account...");
43 return email != null && email.contains("@");
44 }
45
46 @Override
47 public void pay(double amount) {
48 System.out.println("Paid $" + amount + " using PayPal");
49 }
50}
51
52class CryptoPayment implements PaymentStrategy {
53 private String walletAddress;
54
55 public CryptoPayment(String walletAddress) {
56 this.walletAddress = walletAddress;
57 }
58
59 @Override
60 public boolean validate() {
61 System.out.println("Validating crypto wallet...");
62 return walletAddress != null && walletAddress.length() > 20;
63 }
64
65 @Override
66 public void pay(double amount) {
67 System.out.println("Paid $" + amount + " using Cryptocurrency");
68 }
69}
70
71// Context
72class ShoppingCart {
73 private List<Double> items = new ArrayList<>();
74 private PaymentStrategy paymentStrategy;
75
76 public void addItem(double price) {
77 items.add(price);
78 }
79
80 public void setPaymentStrategy(PaymentStrategy strategy) {
81 this.paymentStrategy = strategy;
82 }
83
84 public void checkout() {
85 double total = items.stream().mapToDouble(Double::doubleValue).sum();
86
87 if (paymentStrategy.validate()) {
88 paymentStrategy.pay(total);
89 } else {
90 System.out.println("Payment validation failed!");
91 }
92 }
93}
94
95// Usage
96public class Main {
97 public static void main(String[] args) {
98 ShoppingCart cart = new ShoppingCart();
99 cart.addItem(100.00);
100 cart.addItem(50.00);
101
102 // Pay with credit card
103 cart.setPaymentStrategy(
104 new CreditCardPayment("1234567890123456", "123", "12/25"));
105 cart.checkout();
106
107 // Same cart, different payment
108 cart.setPaymentStrategy(
109 new PayPalPayment("user@email.com", "password"));
110 cart.checkout();
111 }
112}Different payment strategies implement the same interface. The cart can use any payment method without knowing details.
When to Use
Multiple algorithms for same task
Algorithm selection at runtime
To eliminate conditional statements
When algorithms should be independent of clients
Real-World Example
- Sorting algorithms (quick sort, merge sort)
- Compression algorithms (ZIP, RAR, GZIP)
- Route calculation (fastest, shortest, avoid tolls)
- Pricing strategies (regular, discount, loyalty)
💡 Interview Tips
Show payment or sorting example
Explain how it eliminates if/else chains
Discuss runtime algorithm switching
Compare with State pattern (similar but different intent)
Mention it follows Open/Closed Principle