DEV Community

Naresh Babu
Naresh Babu

Posted on

2

Strategy Design Pattern

The Strategy Design Pattern is a behavioral design pattern that enables selecting an algorithm's behavior at runtime.

Instead of implementing multiple variations of an algorithm in a single class, it allows you to define a family of algorithms, encapsulate each in its own class, and make them interchangeable.

Components of the Strategy Pattern (UML):

  1. Context Class: Maintains a reference to a Strategy object and interacts with it through a common interface.

    • Example: The User class interacts with different strategies for Quality and AdPolicy.
  2. Strategy Interface: Defines a common interface for all concrete strategies.

    • Example: Quality and ADPolicies are abstract interfaces defining behavior.
  3. Concrete Strategies: Implement the Strategy interface with specific algorithms.

    • Example: FreeUserQuality, PremiumUserQuality, BasicUserQuality, FreeUserAdPolicy, etc.

When to Use the Strategy Pattern

Use the Strategy Pattern when the benefits of flexibility and maintainability outweigh the overhead of managing multiple strategy classes.

  1. Many Algorithms:

    • When you need to define multiple variations of an algorithm or behavior within a single class.
    • Example: Defining video quality for different subscription plans (Free, Basic, Premium).
  2. Runtime Decisions:

    • When the behavior of a class needs to change dynamically based on user input or other runtime conditions.
    • Example: Selecting compression algorithms (ZIP, RAR, 7z) at runtime.
  3. Avoid Excessive Use of if or switch Statements:

    • Replace conditional logic with interchangeable strategy classes.
    • Example: Payment processing (Credit Card, PayPal, UPI) without a massive if-else block.
  4. Encapsulation of Variations:

    • Encapsulate algorithm variations in separate classes to keep the context class clean.
    • Example: Logging strategies (ConsoleLogger, FileLogger, RemoteLogger).
  5. Open/Closed Principle:

    • Ensure the system is open for extension but closed for modification by adding new strategies without altering existing code.
    • Example: Adding a new user type (EnterpriseUserQuality) in the example system.

Example:

from abc import ABC, abstractmethod
from enum import Enum

# Enum for User Types
class UserType(Enum):
    FREE = 0
    BASIC = 1
    PREMIUM = 2

# Strategy Interface for Quality
class Quality(ABC):
    @abstractmethod
    def get_quality(self):
        pass

# Strategy Interface for Ad Policy
class AdPolicy(ABC):
    @abstractmethod
    def has_ads(self):
        pass

# Concrete Strategy for Quality
class FreeUserQuality(Quality):
    def get_quality(self):
        return ['SD']

class BasicUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD']

class PremiumUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD', 'UHD']

# Concrete Strategy for Ad Policy
class FreeUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class BasicUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class PremiumUserAdPolicy(AdPolicy):
    def has_ads(self):
        return False

# Context Class
class User:
    def __init__(self, user_type: UserType, quality: Quality, ad_policy: AdPolicy):
        self.user_type = user_type
        self.quality = quality
        self.ad_policy = ad_policy

    def get_quality(self):
        return self.quality.get_quality()

    def has_ads(self):
        return self.ad_policy.has_ads()

# Usage
free_user = User(UserType.FREE, FreeUserQuality(), FreeUserAdPolicy())
basic_user = User(UserType.BASIC, BasicUserQuality(), BasicUserAdPolicy())
premium_user = User(UserType.PREMIUM, PremiumUserQuality(), PremiumUserAdPolicy())

print("Free User Quality:", free_user.get_quality())  # ['SD']
print("Free User Ads:", free_user.has_ads())          # True

print("Premium User Quality:", premium_user.get_quality())  # ['SD', 'HD', 'UHD']
print("Premium User Ads:", premium_user.has_ads())          # False
Enter fullscreen mode Exit fullscreen mode

Advantages of the Strategy Pattern:

  1. Flexibility: Algorithms can be swapped at runtime without altering the context class.
  2. Extensibility: New strategies can be added without modifying existing code.
  3. Readability and Maintenance: Reduces clutter in the main class by delegating logic to specific strategy classes.
  4. Adherence to SOLID Principles: Particularly supports the Open/Closed Principle.

Disadvantages of the Strategy Pattern:

  1. Increased Complexity: Introduces additional classes and objects to manage.
  2. Overhead: If the number of strategies is small or infrequently changed, the pattern might add unnecessary complexity.

Additional Examples

  1. Sorting Algorithms: Using different sorting strategies (e.g., QuickSort, MergeSort, BubbleSort) dynamically.
  2. Discount Calculation: Applying different discount strategies (FlatDiscount, PercentageDiscount) based on user type.
  3. Authentication Mechanisms: Switching between different authentication methods (OAuth, JWT, BasicAuth).

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay