Strategy Pattern helps you easily switch between different ways to do a task without changing your main code. It lets you define different methods in separate classes, making your code cleaner and more flexible.
Let’s look at a simple example of the Strategy Pattern using payment methods. In our example application, users have different options for payment:
We first create an interface that defines the method for payment.
interface PaymentStrategy {
pay(amount: number): void;
}
Then we create classes for each payment method, implementing the interface.
class CreditCardPayment implements PaymentStrategy {
pay(amount: number) {...}
}
class PayPalPayment implements PaymentStrategy {
pay(amount: number) {...}
}
class BitcoinPayment implements PaymentStrategy {
pay(amount: number) {...}
}
We can now use PaymentStrategy
as type of an argument in any function or
method, making it easy to swap out different classes.
This approach allows high-level modules to ignore the details of how something works. They only need to know which functions to call through the interface. This follows the Open-Closed Principle, which makes software easy to extend but not change.
Now, let’s continue with our example and use a payment strategy.
class Order {
private paymentStrategy: PaymentStrategy;
constructor(paymentStrategy: PaymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
completeOrder(amount: number) {
this.paymentStrategy.pay(amount);
}
}
const order1 = new Order(new CreditCardPayment());
order1.completeOrder(200); // Order paid using credit card
const order2 = new Order(new PayPalPayment());
order2.completeOrder(100); // Order paid using PayPal
With this example, you can see how the Strategy Pattern allows you to easily switch between different payment methods without changing the core logic of order. Each method is defined separately, making your code cleaner and more maintainable.
Find this post helpful? Subscribe and get notified when I post something new!