Fact-checked by Grok 2 weeks ago

Strategy pattern

The Strategy pattern is a behavioral design pattern that defines a family of interchangeable , encapsulates each as a separate implementing a , and allows clients to select and switch between them at runtime without altering the client code. This pattern enables to vary independently from the clients that use them, promoting flexibility in by avoiding hard-coded conditional logic for selection. Introduced in the 1994 book Design Patterns: Elements of Reusable Object-Oriented Software by , Richard Helm, Ralph Johnson, and John Vlissides—commonly known as the (GoF)—the Strategy pattern addresses common challenges in where multiple variants of an need to be supported dynamically. The pattern's core structure involves three main participants: a class that maintains a reference to a object and delegates algorithm execution to it; a interface or abstract class declaring the algorithm's method; and concrete classes that implement specific algorithms. This composition allows the Context to remain unchanged while swapping strategies, adhering to the open-closed principle by extending behavior through new strategy classes rather than modifying existing code. The Strategy pattern is applicable in scenarios involving families of related algorithms, such as methods, options, or techniques, where the choice of depends on conditions like size or preferences. It is particularly useful for eliminating large switch statements or if-else chains that select behaviors, instead providing a more maintainable and extensible alternative. Key advantages include defining a clear of interchangeable algorithms, enabling reuse across contexts, and simplifying by isolating strategies; however, it can introduce complexity through additional classes and may not be ideal if strategies are few or simple enough for direct parameterization. The pattern relates to others like (which also encapsulates varying behavior but focuses on object state changes) and Flyweight (sharing strategies to optimize memory), and it contrasts with Template Method by allowing full algorithm replacement rather than partial variation.

Definition and Intent

Definition

The Strategy pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one as an object, and makes them interchangeable within the context of a client, allowing the algorithm to vary independently from clients that use it. It consists of three key components: the Context, which is the client class that uses a ; the , an or class that declares the algorithm to be implemented; and ConcreteStrategy, concrete classes that implement the interface to provide specific algorithm behaviors. The pattern was introduced in the 1994 book Design Patterns: Elements of Reusable Object-Oriented Software by , Richard Helm, Ralph Johnson, and John Vlissides, commonly known as the . As a behavioral design pattern, it focuses on the communication between objects, using and to manage algorithms and responsibilities.

Intent and Motivation

The intent of the Strategy pattern is to define a family of algorithms, encapsulate each one within its own class, and make them interchangeable at , allowing the algorithm to vary independently from the clients that use it. This pattern is motivated by scenarios where a single class must perform different behaviors based on varying conditions, such as selecting among multiple algorithms depending on input data or environmental factors. Without Strategy, such flexibility often results in bloated code filled with conditional statements (e.g., numerous if-else branches to choose between sorting algorithms like for large datasets or for small ones), which violates the and makes maintenance difficult. By delegating algorithm selection and execution to interchangeable strategy objects, the pattern separates the concerns of behavior choice from the core logic of the context class, reducing and enabling runtime swaps without client-side modifications. A practical example is a processing that must handle diverse methods like authorization or integration; embedding each method's logic directly in the processor class would lead to entangled code, whereas treating them as strategies allows seamless addition or substitution of options.

Structure

Class Diagram

The class diagram of the pattern depicts a static structure that supports the encapsulation and interchangeability of algorithms through and polymorphism. As outlined in the foundational work on , the diagram features a small set of interrelated classes without complex hierarchies. The primary components include the class, which represents the client that uses the algorithm; the abstract class or interface; and one or more ConcreteStrategy classes. The Context class contains a private reference to a Strategy object, typically named strategy, and includes a public method such as contextInterface() that delegates the core algorithmic work by invoking the Strategy's algorithmInterface() method. The Strategy component declares the abstract algorithmInterface() method, serving as the common contract for all algorithm variants without providing an implementation itself. Each ConcreteStrategy class, such as ConcreteStrategyA or ConcreteStrategyB, implements this method with a specific algorithm, enabling diverse behaviors like sorting via quicksort or mergesort. Key relationships in the diagram consist of a composition association (denoted by a filled diamond) from Context to Strategy, signifying that the Context owns and manages the lifecycle of its Strategy instance; and realization relationships (dashed arrows with hollow triangles) from each ConcreteStrategy to Strategy, indicating implementation of the abstract method. Notably, no inheritance exists between Context and Strategy, preserving their independence. This arrangement facilitates polymorphism, where the Context interacts solely with the Strategy interface, allowing seamless substitution of ConcreteStrategy instances at runtime without modifying the Context code. A frequent variation replaces the Strategy interface with an abstract class to accommodate shared helper methods or default implementations across ConcreteStrategies, such as common preprocessing steps, while still supporting multiple concrete realizations.

Sequence Diagram

The sequence diagram for the Strategy pattern depicts the runtime interactions that enable interchangeable algorithms, focusing on how the Client configures the with a specific strategy and how the Context delegates execution without knowledge of the implementation. As defined in the seminal work by Gamma et al., the diagram includes lifelines for the Client (which initiates the process), the (which maintains a reference to the interface), the abstract Strategy, and one or more instances (which provide the actual algorithmic behavior). The primary flow begins with the Client instantiating a ConcreteStrategy object and passing it to the Context via a setter method, such as setStrategy(). This establishes the polymorphic reference in the . Subsequently, the Client sends a request to the , prompting the to invoke the execute() or equivalent on its Strategy reference. The call resolves dynamically to the ConcreteStrategy's , where the specific is performed, and the result is returned through the chain back to the Client. This interaction highlights runtime polymorphism and encapsulation of implementation details within the strategy objects. Key messages in the sequence include:
  • Client → ConcreteStrategy: new ConcreteStrategy() (instantiation)
  • Client → Context: setStrategy(ConcreteStrategy) (configuration)
  • Client → Context: request() (initiation)
  • Context → Strategy: execute() (delegation)
  • Strategy → self: performAlgorithm() (execution in concrete class, often shown as an activation bar on the ConcreteStrategy lifeline)
To illustrate switching strategies mid-execution, an extended sequence might show the Client sending another setStrategy(new DifferentConcreteStrategy) after an initial request, followed by a second request() that now delegates to the updated strategy, allowing runtime adaptability without modifying the Context. This is particularly evident in the book's motivational example of varying text justification algorithms, where the Context (e.g., a ) can switch between ConcreteStrategies like LeftJustify and CenterJustify based on formatting requirements.

Implementation

Pseudocode

The Strategy pattern is typically implemented through an abstract strategy interface, concrete strategy classes, a context class that delegates to the strategy, and client code that configures and uses the context. This pseudocode provides a language-agnostic outline of the pattern's structure, emphasizing the encapsulation of interchangeable algorithms.

Strategy Interface

The core of the pattern is an abstract Strategy component defining a common interface for all supported algorithms.
interface Strategy {
    algorithm(): result;
}
This interface declares a single abstract method algorithm() that concrete implementations must provide, allowing the context to invoke algorithms uniformly without knowing their specifics.

Concrete Strategies

Concrete strategy classes implement the Strategy interface with specific algorithm logic. For example, two variants might sort data in ascending or descending order.
class ConcreteStrategyA implements Strategy {
    algorithm(): result {
        // Specific logic for algorithm A, e.g., sort ascending
        return "sorted ascending";
    }
}

class ConcreteStrategyB implements Strategy {
    algorithm(): result {
        // Specific logic for algorithm B, e.g., sort descending
        return "sorted descending";
    }
}
Each concrete strategy encapsulates a distinct behavior, enabling runtime selection based on needs.

Context Class

The Context maintains a reference to a Strategy object and delegates algorithm execution to it, promoting flexibility in behavior.
class Context {
    private Strategy strategy;

    constructor(Strategy initialStrategy) {
        this.strategy = initialStrategy;
    }

    setStrategy(Strategy newStrategy) {
        this.strategy = newStrategy;
    }

    contextMethod(): result {
        if (this.strategy == null) {
            throw new Error("No strategy assigned");
        }
        return this.strategy.algorithm();
    }
}
The context uses a private field for the strategy, with a constructor or setter for assignment. The contextMethod() ensures the strategy is not null before delegation to prevent runtime errors, then invokes the algorithm.

Client Usage

A client instantiates strategies, assigns them to a , and invokes the 's to execute the selected .
class Client {
    main() {
        strategyA = new [ConcreteStrategyA](/page/Class)();
        [context](/page/Context) = new [Context](/page/Context)(strategyA);
        resultA = [context](/page/Context).contextMethod();  // Uses ascending sort

        strategyB = new [ConcreteStrategyB](/page/Class)();
        [context](/page/Context).setStrategy(strategyB);
        resultB = [context](/page/Context).contextMethod();  // Switches to descending sort
    }
}
This usage demonstrates dynamic strategy interchangeability at , allowing the same to support varying behaviors without modification.

Language-Specific Example

The is commonly implemented in , an object-oriented language well-suited for demonstrating behavioral through interfaces and polymorphism. The following example adapts the abstract structure to concrete , using simple arithmetic operations ( and ) to show how interchangeable strategies can be applied within a context class.

Strategy Interface

The Strategy interface defines the contract for all concrete strategies, specifying a single method to execute the algorithm with two integer parameters.
java
public interface Strategy {
    int execute(int a, int b);
}

Concrete Strategies

Concrete strategy classes implement the Strategy interface, each encapsulating a specific operation. Addition Strategy:
java
public class ConcreteAdd implements Strategy {
    @Override
    public int execute(int a, int b) {
        return a + b;
    }
}
Subtraction Strategy:
java
public class ConcreteSubtract implements Strategy {
    @Override
    public int execute(int a, int b) {
        return a - b;
    }
}

Context Class

The Context class maintains a reference to a Strategy object and provides methods to set the strategy and delegate execution to it.
java
public class Context {
    private Strategy strategy;

    public Context() {
        // Default strategy can be set here if needed
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        if (strategy == null) {
            throw new IllegalStateException("No strategy set");
        }
        return strategy.execute(a, b);
    }
}

Client Usage

In the client code, a Context instance is created, and different strategies are set and executed at runtime to demonstrate interchangeability. The output shows the results of applying addition and then subtraction to the same inputs.
java
public class Client {
    public static void main(String[] args) {
        [Context](/page/Context) context = new [Context](/page/Context)();

        // Use [addition](/page/Addition) [strategy](/page/Strategy)
        [Strategy](/page/Strategy) addStrategy = new ConcreteAdd();
        context.setStrategy(addStrategy);
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));  // Output: 10 + 5 = 15

        // Switch to subtraction [strategy](/page/Strategy)
        [Strategy](/page/Strategy) subtractStrategy = new ConcreteSubtract();
        context.setStrategy(subtractStrategy);
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));  // Output: 10 - 5 = 5
    }
}
This implementation leverages 's interface-based polymorphism, allowing the Context to remain agnostic to the specific strategy used, as it interacts solely through the Strategy reference. The code compiles with standard Java compilers (e.g., from JDK 8 or later) and runs without additional dependencies, producing the expected output when executed via java Client. Extending the example to include more operations, such as , would involve adding new classes implementing Strategy without modifying existing code.

Benefits and Trade-offs

Advantages

The Strategy pattern enhances flexibility in by enabling the dynamic selection and interchange of algorithms at , without necessitating recompilation or modification of the client code that uses them. This allows developers to extend functionality by introducing new strategies without altering the core class, aligning with the open-closed principle by permitting extension while keeping the system open for modification only through new strategy implementations. By encapsulating each algorithm within its own concrete strategy class, the pattern promotes adherence to the , as each strategy focuses solely on implementing one specific behavior or , thereby isolating changes and reducing the risk of unintended side effects in the broader system. This separation ensures that modifications to a particular affect only its dedicated class, simplifying maintenance and evolution of the codebase. The pattern facilitates reusability by allowing individual strategy classes to be shared across multiple context classes or even different applications, promoting the creation of modular, interchangeable components that can be composed into various configurations without duplication. This approach leverages object-oriented composition to build families of related behaviors that can be reused independently of their usage context. Testability is improved through the isolation of strategies, enabling unit tests to target each algorithm independently without the need to instantiate or mock the entire context, which eliminates the complexity of testing conditional logic scattered across multiple if-else branches in monolithic implementations. This modular structure supports more focused and efficient testing practices, as each strategy can be verified in isolation for correctness and performance. For instance, in a application, the Strategy pattern allows seamless switching between routing algorithms—such as one prioritizing the fastest path versus another favoring scenic routes—by injecting the appropriate strategy into the context at , thereby adapting to user preferences without refactoring the application's core logic.

Disadvantages

The Strategy pattern introduces additional classes, one for each distinct algorithm or behavior, which can increase the overall of the by expanding the number of components that must be managed and understood. This proliferation of classes often results in more objects being instantiated at , potentially complicating and efforts. A key drawback is the added responsibility placed on the client code, which must be aware of the available strategies and capable of selecting the appropriate one based on context or requirements. This awareness can expose implementation details to the client, potentially leading to tighter or errors if the differences between strategies are not well-documented or intuitive. The pattern incurs a minor performance overhead stemming from dynamic dispatch mechanisms, such as virtual function calls, and the costs associated with creating and switching between strategy objects, which may be negligible in most applications but noticeable in performance-critical scenarios. Additionally, frequent communication between the context and strategy objects can introduce further overhead if not minimized through stateless designs. For cases involving only a handful of stable algorithms that rarely evolve, the Strategy pattern may overcomplicate the solution unnecessarily, as simpler approaches like conditional statements within the context class would suffice without the added abstraction layers. In resource-constrained environments, such as embedded systems, the increased number of strategy objects can exacerbate memory usage issues, making the pattern less suitable where efficiency is paramount over flexibility.

Relation to Other Concepts

Open-Closed Principle

The Open-Closed Principle (OCP), introduced by in 1988, states that software entities such as classes, modules, and functions should be open for extension but closed for modification. This principle promotes designs where new functionality can be added through extension mechanisms like or , without altering the source code of existing components, thereby reducing the risk of introducing bugs during modifications. The Strategy pattern aligns with the OCP by allowing the Context class to remain unchanged when new behaviors are introduced through additional ConcreteStrategy classes. Extension occurs by creating new strategy implementations that adhere to the Strategy interface, enabling the system to incorporate varied algorithms without modifying the core Context logic or existing strategies. This adherence to OCP is evident in scenarios where the pattern encapsulates interchangeable algorithms, such as sorting methods in a data processing library, where new sorting variants can be added independently. The mechanism supporting this alignment relies on polymorphism and : the delegates behavior to a object via an reference, permitting runtime substitution without internal changes to the or Client code. For instance, in an e-commerce order processing system, introducing a new strategy (e.g., ) involves only defining a new ConcreteStrategy class, leaving the OrderProcessor () unmodified. However, the Strategy pattern's support for OCP has limitations; while the Context and existing strategies remain closed to modification, Client code may require updates to instantiate and select the new strategies, potentially introducing minor modifications outside the core entities.

Comparison with State Pattern

The State pattern enables an object to alter its behavior when its internal state changes, making it appear as though the object has changed its class; it encapsulates state-specific behavior by delegating to state objects that can trigger transitions between states. In contrast, the pattern defines a family of interchangeable algorithms, encapsulating each in its own class and allowing a client to select and switch them at without altering the object. The primary difference lies in and : focuses on external selection of independent algorithms, often bound once at initialization for pluggable behaviors, whereas State manages dynamic internal transitions where states may depend on and modify the context's state. Both patterns share structural similarities as behavioral designs from the catalog, relying on composition and polymorphism: a delegates varying behavior to interchangeable objects via a , promoting and adherence to the open-closed principle. However, treats algorithms as less and unaware of each other, avoiding interdependencies, while introduces potential cycles or dependencies as states can invoke context methods to change the current . Choose the Strategy pattern when the goal is to support multiple, interchangeable algorithms independent of the object's state, such as selecting different sorting methods in a data processor. Opt for the State pattern when behavior inherently depends on the object's lifecycle or internal conditions, like managing play, pause, and stop states in a media player where each state dictates valid transitions. For instance, a file compression tool might use Strategy to swap algorithms like ZIP or GZIP externally based on user preference, without internal state changes, whereas a TCP connection handler employs State to evolve through listening, established, and closed phases, with each phase restricting actions.

Relation to Flyweight Pattern

The is a structural that minimizes memory usage by sharing as much data as possible between similar objects. The Strategy pattern relates to Flyweight when strategies are stateless and can be shared among multiple contexts to optimize resource usage. In the Gang of Four's description, shared strategies act as flyweights if they do not maintain state across invocations. This combination is useful in scenarios with many contexts using the same algorithm, such as in graphics rendering where common rendering strategies are reused across numerous objects.

Comparison with Template Method Pattern

The Template Method pattern is a behavioral design pattern that defines the skeleton of an algorithm in a base class, allowing subclasses to override specific steps without changing the overall structure. In contrast to , which uses to allow full runtime replacement of algorithms, Template Method relies on inheritance for compile-time variation of algorithm parts. Strategy provides greater flexibility for switching entire behaviors dynamically, while Template Method ensures a fixed sequence with customizable hooks, making it suitable for frameworks where the algorithm outline is invariant but details vary.

References

  1. [1]
    Design Patterns: Elements of Reusable Object-Oriented Software
    Design Patterns: Elements of Reusable Object-Oriented Software. by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides ... Pattern Catalog · Chapter 3 ...
  2. [2]
    Strategy - UNC Computer Science
    The Strategy pattern has the following benefits and drawbacks: Families of related algorithms. Hierarchies of Strategy classes define a family of algorithms ...Missing: design | Show results with:design
  3. [3]
    Design Patterns: Elements of Reusable Object-Oriented Software
    30-day returnsOct 31, 1994 · The authors begin by describing what patterns are and how they can help you design object-oriented software. They then go on to systematically ...
  4. [4]
    Strategy - Refactoring.Guru
    Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects ...Strategy in C# / Design Patterns · Strategy in Python · Strategy in C++ · Java
  5. [5]
    Strategy Design Pattern - GeeksforGeeks
    Sep 26, 2025 · Strategy Design Pattern is a behavioral design pattern that allows you to define a family of algorithms or behaviors, put each of them in a ...
  6. [6]
    Strategy Pattern - Spring Framework Guru
    The Behavioral pattern family of the Gang of Four design patterns address responsibilities of objects in an application and how they communicate between them at ...
  7. [7]
    Strategy Design Pattern - SourceMaking
    Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.Strategy in C++ · Strategy in Delphi · Strategy in PHP · Strategy in Java
  8. [8]
    Strategy Design Pattern in Java - Dot Net Tutorials
    What is Strategy Design Pattern? According to the Gang of Four Definitions, define a family of algorithms, encapsulate each one, and make them interchangeable.Missing: applicability | Show results with:applicability
  9. [9]
    [PDF] Strategy Design Pattern
    Advantages: 1. Allows you to have more options. Clients will have more choices ... [1] Vlissides, J., Helm, R., Johnson, R. and Gamma, E., 1995. Design ...
  10. [10]
    Chapter 6: Design Patterns – Software Engineering
    Among the design patterns proposed in the Gang of Four book, Singleton is probably the most controversial and criticized. The reason is that it can be used to ...
  11. [11]
    Strategy Pattern, page 3
    Consequences. The strategy pattern has the following consequences and drawbacks. Families of related algorithms. Algorithms are arrange into an inheritance ...
  12. [12]
    [PDF] The Open-Closed Principle - Object Mentor
    Bertrand Meyer2 gave us guidance as long ago as 1988 when he coined the now famous open-closed principle. To paraphrase him: SOFTWARE ENTITIES (CLASSES, MODULES ...
  13. [13]
    [PDF] PRINCIPLES OF DESIGN PATTERNS
    Nov 1, 2011 · Single Responsibility Principle (SRP). Every object in your system ... Strategy Pattern. Code to an interface (the algorithm). Prefer ...
  14. [14]
    State - Refactoring.Guru
    Intent. State is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its ...State in C# / Design Patterns · State in Java · State in Python · State in C++
  15. [15]
    State Design Pattern - SourceMaking
    The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic). The structure of State and Bridge are identical (except ...