Back to all terms
S1S2
State & Archbasic

Strategy Pattern

A behavioral design pattern that defines a family of interchangeable algorithms, encapsulates each one, and allows the algorithm to be selected at runtime.

Also known as: Policy Pattern, Pluggable Algorithm, Interchangeable Behavior

Description

The Strategy pattern defines a family of algorithms or behaviors, encapsulates each one as a separate class or function, and makes them interchangeable through a common interface. The context object delegates algorithm execution to the current strategy object, which can be swapped at runtime. This eliminates conditional branching (long if-else or switch chains) by replacing them with polymorphism, adhering to the Open-Closed Principle: new strategies can be added without modifying existing code.

In TypeScript, strategies are naturally expressed as interfaces with a single method. A PricingStrategy interface with calculate(order: Order): Money can have implementations for StandardPricing, VolumePricing, SubscriberPricing, and PromotionalPricing. The OrderService receives the appropriate strategy based on the customer type or active promotions. In functional programming, strategies simplify to higher-order functions: sort(array, compareFn) is the Strategy pattern where compareFn is the strategy. React's render props and component injection (passing a component as a prop) are also strategy pattern applications.

The Strategy pattern is particularly valuable when an application has multiple ways of doing the same thing and the choice varies by configuration, user, or context: sorting algorithms, compression methods, authentication providers, notification channels, payment processors, or tax calculation rules. The pattern makes each variant independently testable and deployable. The key design decision is where the strategy selection happens—the client can choose directly, or a factory can select the strategy based on context, which is often cleaner for complex selection logic.

Prompt Snippet

Define a NotificationStrategy interface with a single method send(recipient: User, message: NotificationPayload): Promise<NotificationResult>, and implement EmailStrategy (using Resend SDK), SlackStrategy (using Slack Web API), and PushStrategy (using Firebase Cloud Messaging). Create a NotificationService that receives a Map<NotificationChannel, NotificationStrategy> via constructor injection and dispatches to the appropriate strategy based on the user's notification preferences stored in their profile. Add a CompositeStrategy that sends to multiple channels simultaneously using Promise.allSettled and returns a merged result. Each strategy should be independently unit-testable by mocking only its external SDK dependency.

Tags

design-patternsbehavioralgang-of-fourpolymorphismsolid-principles