Thursday, May 02, 2024

Strategy Design Patter in Java

 The Strategy Design Pattern is a delightful way to manage different algorithms within your software. It’s like having a toolbox where each tool (algorithm) is neatly organized and can be swapped out as needed. This pattern is a gem for situations where you have multiple ways to perform a task and want to pick the best one at the moment, without changing the code that uses these tasks.

Imagine you’re cooking, and you have several ways to prepare a dish. With the Strategy Pattern, you can easily switch between different cooking methods (algorithms) without changing the recipe (client code).

Here’s a gentle overview of its components:

Context: Think of this as the recipe that needs to be prepared. It holds a reference to the cooking method (strategy) and is in charge of executing it.
Strategy: This is like the interface that all cooking methods share. It’s the common language that the recipe uses to communicate with the cooking method.
Concrete Strategy: This is the actual cooking method, implementing the strategy interface and defining the specific way to prepare the dish.
So, whether you’re coding or cooking, the Strategy Pattern is your go-to for flexibility and adaptability. It’s a gentle way to ensure your code or recipe can handle a variety of tasks or ingredients with ease.

Example in Java
Let’s consider a simple example where we have a PaymentProcessor class that can process payments using different payment methods (e.g., Credit Card, PayPal, Bank Transfer).

Step 1: Define the Strategy Interface

1
2
3
public interface PaymentStrategy {
    void pay(int amount);
}

Step 2: Implement Concrete Strategies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class CreditCardStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using Credit Card.");
    }
}
 
public class PayPalStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using PayPal.");
    }
}
 
public class BankTransferStrategy implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using Bank Transfer.");
    }
}

Step 3: Define the Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PaymentProcessor {
    private PaymentStrategy paymentStrategy;
 
    public PaymentProcessor(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
 
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
 
    public void pay(int amount) {
        paymentStrategy.pay(amount);
    }
}

Step 4: Use the Strategy Pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Main {
    public static void main(String[] args) {
        PaymentProcessor paymentProcessor = new PaymentProcessor(new CreditCardStrategy());
        paymentProcessor.pay(100);
 
        // Changing payment strategy at runtime
        paymentProcessor.setPaymentStrategy(new PayPalStrategy());
        paymentProcessor.pay(200);
 
        paymentProcessor.setPaymentStrategy(new BankTransferStrategy());
        paymentProcessor.pay(300);
    }
}

Explanation
The PaymentProcessor class is the context. It uses a PaymentStrategy to perform the payment.
The PaymentStrategy interface defines the method pay(int amount) that all concrete strategies must implement.
CreditCardStrategy, PayPalStrategy, and BankTransferStrategy are concrete strategies that implement the PaymentStrategy interface.
The PaymentProcessor can change its payment strategy at runtime by calling setPaymentStrategy(PaymentStrategy paymentStrategy). This allows the client to choose the appropriate payment method dynamically.

No comments: