What is Strategy Design Pattern?

Introduction

The Strategy Pattern is a behavioural design pattern that allows for interchangeable algorithms within an object at runtime. In other words, it enables you to select an algorithm from a family of algorithms and use it as per your requirements.

In this blog post, we will explain the concept of the Strategy Pattern in detail, including its components, benefits, and a real-world example.

Components

The Strategy Pattern consists of three main components:

  1. Context: Context is an object that maintains a reference to a Strategy object and delegates work to it.

  2. Strategy: The Strategy is an interface that defines a set of methods that are to be implemented by each concrete strategy. The Strategy interface ensures that each concrete strategy implements the same set of methods, which allows them to be interchangeable within the Context object.

  3. Concrete Strategy: The Concrete Strategies are the actual implementations of the algorithms defined by the Strategy interface. They are interchangeable with each other and can be swapped in and out of the Context object at runtime.

Structure

+-----------------+          +------------------+
|     Context     |          |     Strategy     |
+-----------------+          +------------------+
| -strategy:Strategy|<------- | <<interface>>    |
+-----------------+          |   +algorithm()    |
                              +------------------+
                              | ConcreteStrategy |
                              +------------------+
                              | +algorithm()     |
                              +------------------+

Benefits

  1. It promotes the use of the open-closed principle, which means that the code is open for extension but closed for modification. This allows for new strategies to be added without changing the existing code.

  2. It enables the separation of the algorithm implementation from the client code, which makes the code more modular and easier to maintain.

  3. It allows for runtime switching of strategies, which can be useful in situations where different algorithms are required depending on the input data or other factors.

Example

Let's consider an example of a shopping cart system. In this system, we have a ShoppingCart class that maintains a list of items to be purchased. We want to implement a discount system that applies different discounts to the items in the cart based on the customer's loyalty status. We can use the Strategy Pattern to implement this feature.

First, we define a DiscountStrategy interface that has a method to calculate the discount:

interface DiscountStrategy {
    double calculateDiscount(double totalPrice);
}

Next, we implement two Concrete Strategies that implement the DiscountStrategy interface:

class BronzeDiscountStrategy implements DiscountStrategy {
    public double calculateDiscount(double totalPrice) {
        return totalPrice * 0.05;
    }
}

class SilverDiscountStrategy implements DiscountStrategy {
    public double calculateDiscount(double totalPrice) {
        return totalPrice * 0.10;
    }
}

In the ShoppingCart class, we maintain a reference to the DiscountStrategy object and use it to calculate the discount:

class ShoppingCart {
    private List<Item> items;
    private DiscountStrategy discountStrategy;

    public ShoppingCart(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public void addItem(Item item) {
        items.add(item);
    }

    public double getTotalPrice() {
        double totalPrice = 0;
        for (Item item : items) {
            totalPrice += item.getPrice();
        }
        return totalPrice;
    }

    public double calculateDiscount() {
        return discountStrategy.calculateDiscount(getTotalPrice());
    }
}

Finally, we can create different instances of the ShoppingCart class, each with a different DiscountStrategy object, and use them to calculate discounts for different types of customers:

ShoppingCart bronzeCart = new ShoppingCart(new BronzeDiscountStrategy());
double bronzeDiscount = bronzeCart.calculateDiscount();

ShoppingCart silverCart = new ShoppingCart(new SilverDiscountStrategy());
double silverDiscount = silverCart.calculateDiscount();

Conclusion

The Strategy Pattern is a powerful design pattern that allows for interchangeable algorithms within an object at runtime. It promotes the use of the open-closed principle and enables the separation of the algorithm implementation from the client code. By using the Strategy Pattern, we can create more modular, flexible, and maintainable code.

Image Source: https://www.dofactory.com/images/diagrams/net/strategy.gif

Did you find this article valuable?

Support Bit Fetch by becoming a sponsor. Any amount is appreciated!