×

Strategy Design Pattern with Python

Strategy Design Patterns Python Feature

Strategy Design Pattern is prefered to use within the applications where the underlying algorithms need to be selected at runtime.

Strategy Pattern suggests introducing an interface, which can enable the functionality to choose the algorithm at run time.

Strategy-Interface, which helps to select algorithms at run time, defines each and every algorithm, encapsulates the algorithms and makes algorithms interchangeable.

Strategy Pattern is one of the Behavioural Design Patterns as it enables an algorithm’s behaviour to be selected at runtime.

Usage

If software applications need to change their functionality depending on the user’s choices, data sources, or other factors. Developers have a few alternatives to accomplish such tasks.

In such scenarios, algorithms can be defined under conditional statements for different situations. But, the conditional statements are not elegant solutions, as conditional statements make the code quite lengthy and decrease the maintainability of the application.

In situations like these, the strategy pattern is an ideal solution. 

One example of an application using Strategy Pattern would be, a chess application, where the selection of the difficulty level-easy, medium, or hard, by a user, decides the selection of algorithm by the computer. This is one of the best examples where the strategy pattern can be used.

Implementation

  • Context interface: Interface that keeps a reference to all available strategies(algorithm).
class Cotext:
    def __init__(self, strategy):
        self._strategy = strategy

    def context_interface(self):
        self._strategy.algorithm_interface()
  • Strategy interface: An abstract interface, defining the structure for all the available concrete strategies.
class Strategy():    
    @abstractmethod
    def algorithm_interface(self):
        pass
  • Concrete Strategy Interfaces: Interfaces implementing all available strategies(i.e algorithms).
class Strategy_A(Strategy):
    """Implementation of Algotihms"""
    def algorithm_interface(self):
        pass
class Strategy_B(Strategy):
    def algorithm_interface(self):
        pass

Example:

An application deciding which discount offer to apply on shopping amount.

  • Product class, serving as context class.
class Product:
    """Context class"""
    def __init__(self, price, strategy = None):
        self.price = price
        self.strategy = strategy
		
    def price_after_discount(self):
        if self.strategy:
            discount = self.strategy.discount(self.price)
        else:
            discount = 0
        return self.price - discount

    def __str__(self):        
        return f"Price: {self.price}, price after discount: {self.price_after_discount()}"
  • Concrete strategies
class Sale_Discount:
    def discount(price):
	    return price * 0.25 + 20
class Regular_Discount:
    def discount(price):
	    return price * 0.20
  • The Driver Code
if __name__ == "__main__":

	print(Product(20000))
	print(Product(20000, strategy = Sale_Discount))
	print(Product(20000, strategy = Regular_Discount))
Output
Price: 20000, price after discount: 20000              
Price: 20000, price after discount: 14980.0
Price: 20000, price after discount: 16000.0

In this article, we have seen where and how to use the strategy pattern in your code. Using the strategy pattern makes software applications flexible and maintainable. Enables to switch between algorithms at runtime according to the user’s decision without changing the code.

If code only has a couple of algorithms, there is no need to use strategy. Strategy pattern makes the code look complex with numerous classes and objects. The Strategy pattern can work as an alternative for conditional statements for selecting the behaviour of the application.