The Strategy Design Pattern is a fundamental component of behavioral design patterns in software engineering. It serves a crucial role in structuring and organizing algorithms and behaviors within a software system. In essence, this pattern revolves around the concept of providing a structured and interchangeable set of algorithms while allowing clients to select and switch between these algorithms dynamically, all without the need to alter existing code. This sophisticated mechanism not only enhances the maintainability of the code-base but also significantly contributes to code reusability and flexibility.
Components of the Strategy Pattern
- Context: This is the class that maintains a reference to the strategy interface and can switch between different strategies. It delegates the algorithm to the strategy object. (The handsome human in the above banner 😉)
- Strategy: The interface or abstract class that defines the contract for concrete strategies. All concrete strategies must implement this interface.(The payment screen in the banner)
- Concrete Strategy: These are the actual implementations of the strategy interface. They contain specific algorithms that the context can use. (The individual payment methods)
When to Use the Strategy Pattern
The Strategy Pattern becomes particularly relevant when:
- You have multiple related algorithms or behaviors that vary in their implementation.
- You want to allow clients to choose an algorithm at runtime.
- You want to isolate the client code from the specifics of algorithm implementations.
- You want to avoid code duplication by promoting code reusability.
Let’s dive in to see a real world example
Let’s say we want to create a simple shopping cart application where we can calculate the total cost of items in the cart after applying some discount (which obviously everyone like). We’ll define different strategies for calculating the total cost based on different types of discounts. To achieve that we do as follows:
- Define the Discount Strategy Interface:
2. Define concrete implementations of the type of discounts you want to offer, for ex: percentage discount, fixed discount of $100, etc.
3. Create a Shopping Cart Class and use the Discount Strategy using:
Note: Here for my example I’ve used a composition relation between Shopping Cart and Discount Strategy, another way of implementation is using association. (For those who don’t know, Composition relation means every Shopping cart object needs creation of a Discount Strategy object; i.e. they are strongly associated. Using Association, would have just given us the flexibility to create Shopping Cart object with creation of Discount Strategy object.)
And, we are done!!!
Now to see the above created class in action we can create a driver class ShoppingApp.
We created different discount strategies (No Discount, Percentage Discount, and Fixed Discount) and used them interchangeably in the ShoppingCart class to calculate the total cost based on the selected strategy. This demonstrates the Strategy Pattern, allowing you to switch between different discount calculation algorithms without modifying the ShoppingCart class.
In the above analogy, ShoppingCart class is our context, DiscountStrategy is the strategy and NoDiscountStrategy, PercentageDiscountStrategy & FixedDiscountStrategy are the concrete implementation of our strategy.
General Template of Strategy Pattern:
This generic template demonstrates that the context contains an object of strategy interface(or abstract class) which has 2 or more concrete implementations and the context can use any of the implementation during the runtime without any change in the context class.
Summarizing
Strategy Patterns provides us:
1. Family of Interchangeable Algorithms that can be changed during run-time.
2. Encapsulation of Algorithms into individual implementations.
3. Code Reusability: Since algorithms are encapsulated independently, they can be reused across different parts of the application or even in entirely different projects. This reusability reduces redundancy, saves development time, and maintains consistency in algorithm implementations.
4. Scalability of Design: Any new requirement can easily be catered by simply creating a new strategy implementation which inherits the strategy interface.
Conclusion
The Strategy Design Pattern is a powerful tool for managing interchangeable algorithms in your applications. It promotes code reusability, flexibility, and clean code practices. By encapsulating algorithms in separate strategy classes and allowing the client to switch between them dynamically, we can build more maintainable and scalable software.
For any doubts in the above explanation feel free to reach me at — ankitpandeycu@gmail.com
Share this blog with your peers if you find it useful.
Hope it helps!
AnkitCode99 here….