Bird
Raised Fist0
LLDsystem_design~25 mins

Strategy pattern in LLD - System Design Exercise

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Design: Strategy Pattern Implementation
Design and implement the Strategy pattern for a simple context that can switch between different algorithms dynamically. Out of scope: complex UI integration or persistence.
Functional Requirements
FR1: Allow an object to change its behavior at runtime
FR2: Support multiple interchangeable algorithms or strategies
FR3: Enable adding new strategies without modifying existing code
FR4: Clients should interact with a common interface to use strategies
Non-Functional Requirements
NFR1: Design should follow Open/Closed Principle
NFR2: Strategy switching should be efficient with minimal overhead
NFR3: Code should be easy to understand and maintain
Think Before You Design
Questions to Ask
❓ Question 1
❓ Question 2
❓ Question 3
❓ Question 4
Key Components
Context class that uses a strategy
Strategy interface defining common behavior
Concrete strategy classes implementing different algorithms
Design Patterns
Strategy pattern for behavior encapsulation
Dependency Injection to provide strategies to context
Factory pattern to create strategy instances if needed
Reference Architecture
  +-----------------+       uses       +---------------------+
  |     Context     |----------------->|     Strategy         |
  |-----------------|                  |---------------------|
  | - strategy:Strategy|                | + executeAlgorithm() |
  | + setStrategy()  |                  +---------------------+
  | + performTask()  |                          ^
  +-----------------+                          |
           |                                   |
           |                                   |
  +-----------------+                +---------------------+
  | ConcreteStrategyA|                | ConcreteStrategyB    |
  |-----------------|                |---------------------|
  | + executeAlgorithm()|             | + executeAlgorithm() |
  +-----------------+                +---------------------+
Components
Context
Any OOP language
Holds a reference to a Strategy and delegates behavior execution to it
Strategy Interface
Any OOP language interface or abstract class
Defines a common method for all supported algorithms
Concrete Strategies
Any OOP language classes
Implement different algorithms or behaviors following the Strategy interface
Request Flow
1. Client creates a Context object
2. Client creates a Concrete Strategy object
3. Client sets the Concrete Strategy on the Context using setStrategy()
4. Client calls performTask() on Context
5. Context delegates the call to the current Strategy's executeAlgorithm() method
6. Strategy executes its specific algorithm and returns the result
7. Context returns or uses the result as needed
Database Schema
Not applicable for this design pattern as it focuses on behavior encapsulation in code.
Scaling Discussion
Bottlenecks
Too many strategies can make management complex
Switching strategies frequently may add overhead
Strategies tightly coupled to context can reduce flexibility
Solutions
Use a Factory or Registry to manage strategy instances
Cache or reuse strategy instances when possible
Keep strategies stateless or minimize shared state to improve reusability
Interview Tips
Time: Spend 5 minutes explaining the problem and requirements, 15 minutes designing the pattern with examples, and 5 minutes discussing scaling and trade-offs.
Explain the problem of changing behavior dynamically
Describe how Strategy pattern encapsulates algorithms
Show how Open/Closed Principle is followed
Discuss how client interacts only with context and strategy interface
Mention benefits like easier testing and maintenance
Talk about potential overhead and how to mitigate it

Practice

(1/5)
1. What is the main purpose of the Strategy pattern in system design?
easy
A. To restrict object creation to a single instance
B. To allow selecting an algorithm's behavior at runtime without changing the client code
C. To define a fixed sequence of steps for an algorithm
D. To create a single global instance of a class

Solution

  1. Step 1: Understand the Strategy pattern goal

    The Strategy pattern is designed to let you swap algorithms or behaviors dynamically without changing the client code.
  2. Step 2: Compare options with pattern purpose

    To allow selecting an algorithm's behavior at runtime without changing the client code correctly states this purpose. Options A and B describe Singleton pattern, and C describes Template Method pattern.
  3. Final Answer:

    To allow selecting an algorithm's behavior at runtime without changing the client code -> Option B
  4. Quick Check:

    Strategy pattern = runtime algorithm selection [OK]
Hint: Strategy pattern = choose behavior at runtime [OK]
Common Mistakes:
  • Confusing Strategy with Singleton pattern
  • Thinking Strategy fixes algorithm steps
  • Assuming Strategy creates single instances
2. Which of the following is the correct way to define a Strategy interface in a typical object-oriented language?
easy
A. class Strategy { void execute(); }
B. def Strategy(): pass
C. interface Strategy { void execute(); }
D. struct Strategy { void execute(); }

Solution

  1. Step 1: Identify the correct syntax for interface definition

    In many object-oriented languages like Java or C#, interface keyword is used to define a Strategy interface with method signatures.
  2. Step 2: Evaluate options

    interface Strategy { void execute(); } uses interface with method execute(), which is correct. class Strategy { void execute(); } defines a class, not an interface. def Strategy(): pass is Python syntax but incomplete. struct Strategy { void execute(); } uses struct which is not typical for interfaces.
  3. Final Answer:

    interface Strategy { void execute(); } -> Option C
  4. Quick Check:

    Strategy interface = interface with method [OK]
Hint: Strategy interface uses 'interface' keyword in OOP [OK]
Common Mistakes:
  • Using class instead of interface for Strategy
  • Confusing struct with interface
  • Using incomplete or wrong language syntax
3. Given the following code snippet using the Strategy pattern, what will be the output?
class Context:
    def __init__(self, strategy):
        self.strategy = strategy
    def execute(self):
        return self.strategy.do_action()

class StrategyA:
    def do_action(self):
        return 'Action A'

class StrategyB:
    def do_action(self):
        return 'Action B'

context = Context(StrategyB())
print(context.execute())
medium
A. Action B
B. Action A
C. Error: StrategyB has no method do_action
D. None

Solution

  1. Step 1: Trace object creation and method calls

    The Context is created with StrategyB() instance. Calling context.execute() calls StrategyB.do_action().
  2. Step 2: Check StrategyB.do_action() return value

    StrategyB.do_action() returns the string 'Action B', so print(context.execute()) outputs 'Action B'.
  3. Final Answer:

    Action B -> Option A
  4. Quick Check:

    Context with StrategyB = 'Action B' output [OK]
Hint: Context calls strategy's method, output matches chosen strategy [OK]
Common Mistakes:
  • Assuming default strategy is StrategyA
  • Thinking method do_action is missing
  • Confusing class and instance usage
4. Identify the error in the following Strategy pattern implementation:
class Context:
    def __init__(self, strategy):
        self.strategy = strategy
    def execute(self):
        return self.strategy.action()

class StrategyA:
    def do_action(self):
        return 'Action A'

context = Context(StrategyA())
print(context.execute())
medium
A. Context calls a method 'action' which does not exist in StrategyA
B. StrategyA class is missing the constructor
C. Context should not store strategy as an instance variable
D. No error, code runs correctly

Solution

  1. Step 1: Compare method names between Context and StrategyA

    Context calls self.strategy.action(), but StrategyA defines do_action(), not action().
  2. Step 2: Identify mismatch causing error

    This mismatch causes an AttributeError at runtime because action() is undefined in StrategyA.
  3. Final Answer:

    Context calls a method 'action' which does not exist in StrategyA -> Option A
  4. Quick Check:

    Method name mismatch = runtime error [OK]
Hint: Check method names match between context and strategy [OK]
Common Mistakes:
  • Ignoring method name mismatch
  • Assuming missing constructor causes error
  • Thinking strategy should not be stored in context
5. You are designing a payment system that supports multiple payment methods (credit card, PayPal, cryptocurrency). How would applying the Strategy pattern improve your system design?
hard
A. It requires hardcoding all payment methods inside a single class
B. It forces all payment methods to share the same implementation details
C. It prevents runtime selection of payment methods
D. It allows adding new payment methods without changing existing code by defining each as a separate strategy

Solution

  1. Step 1: Understand Strategy pattern benefits in payment methods

    Strategy pattern lets you define each payment method as a separate strategy class implementing a common interface.
  2. Step 2: Analyze how this affects system design

    This design allows adding new payment methods easily without modifying existing code, and lets the system select payment method at runtime.
  3. Final Answer:

    It allows adding new payment methods without changing existing code by defining each as a separate strategy -> Option D
  4. Quick Check:

    Strategy pattern = easy extension and runtime choice [OK]
Hint: Strategy pattern enables easy addition and runtime choice [OK]
Common Mistakes:
  • Thinking Strategy forces shared implementation
  • Believing all methods must be hardcoded together
  • Assuming runtime selection is not possible