A behavioral design pattern that lets you define a family of algorithms, encapsulate each one, and make them interchangeable. Allows switching between algorithms at runtime.
class PaymentStrategy {
constructor() {
this.type = 'base';
}
// Abstract method to process payment
pay(amount) {
throw new Error('This method must be implemented');
}
}
class CreditCardPayment extends PaymentStrategy {
constructor(cardNumber) {
super();
this.cardNumber = cardNumber;
this.type = 'creditCard';
}
// Process credit card payment
pay(amount) {
return `Processed $${amount} via credit card ending in ***${this.cardNumber.slice(-4)}`;
}
}
class PayPalPayment extends PaymentStrategy {
constructor(email) {
super();
this.email = email;
this.type = 'paypal';
}
// Process PayPal payment
pay(amount) {
return `Processed $${amount} via PayPal for ${this.email}`;
}
}
Use strategy pattern when you have multiple algorithms that perform the same task but differ in implementation. It's ideal for situations where you want to change algorithms dynamically without changing client code.
Unlike the State pattern which manages internal state changes, Strategy focuses on algorithm encapsulation and switching. It provides more flexibility than inheritance for algorithm variations.
Common use cases include payment processing systems, sorting algorithms with different strategies, and data validation frameworks where different validation rules can be applied dynamically.