โ† Back to Design Patterns
โ™Ÿ๏ธ
Behavioral

Strategy

Defines a family of interchangeable algorithms and lets you swap them at runtime.

The Problem

A class has multiple variants of an algorithm, selected with a big if/else or switch. Adding a new variant requires modifying the class itself.

How It Works

  • โ€บEncapsulates each algorithm behind a common interface
  • โ€บAlgorithms can be swapped at runtime without changing the context class
  • โ€บEliminates large conditional blocks for algorithm selection
  • โ€บContext delegates work to the strategy โ€” it does not perform the algorithm itself
  • โ€บClosely related to dependency injection โ€” inject the strategy from outside

When to Use

โœ“Multiple related algorithms that differ only in their behavior
โœ“Swappable behaviors: sorting, compression, payment, validation
โœ“Replacing large if/else chains that select an algorithm
โœ“When you want to let users configure or extend behavior

Real-World Examples

๐ŸŽ
iOS

JSONEncoder.dateEncodingStrategy, URLSessionConfiguration, UICollectionViewLayout

๐Ÿค–
Android

RecyclerView.LayoutManager (Linear/Grid/Staggered), Room TypeConverter

๐ŸŒ
Web

Passport.js strategies (local, OAuth), webpack's loader config, sorting comparators

Code Examples

Swift
protocol ValidationStrategy {
    func validate(_ input: String) -> Bool
}

struct EmailValidator: ValidationStrategy {
    func validate(_ input: String) -> Bool {
        input.contains("@") && input.contains(".")
    }
}

struct PhoneValidator: ValidationStrategy {
    func validate(_ input: String) -> Bool {
        input.allSatisfy { $0.isNumber } && input.count >= 10
    }
}

struct MinLengthValidator: ValidationStrategy {
    let minLength: Int
    func validate(_ input: String) -> Bool { input.count >= minLength }
}

class InputField {
    var strategy: ValidationStrategy

    init(strategy: ValidationStrategy) { self.strategy = strategy }

    func isValid(_ input: String) -> Bool { strategy.validate(input) }
}

let emailField = InputField(strategy: EmailValidator())
print(emailField.isValid("agus@example.com"))  // true
print(emailField.isValid("not-an-email"))      // false

emailField.strategy = MinLengthValidator(minLength: 6)
print(emailField.isValid("hello"))             // false