[2026] C++ Strategy Pattern: Complete Guide | Algorithms, Lambdas & std::function

[2026] C++ Strategy Pattern: Complete Guide | Algorithms, Lambdas & std::function

이 글의 핵심

Strategy pattern in C++: polymorphic strategies, function pointers, lambdas, std::function—sorting and compression examples; performance trade-offs for SEO.

Behavioral patterns are covered in C++ behavioral patterns #20-1 and the overview #20-2.

What is Strategy Pattern? why you need it

Problem Scenario: Hardcoding the Algorithm

Problem: If the logic for selecting a sorting algorithm is hardcoded in the Context, Context must be modified when adding a new algorithm. 아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// Bad example: hardcoding the algorithm
class Sorter {
public:
    void sort(std::vector<int>& data, const std::string& algorithm) {
        if (algorithm == "bubble") {
// bubble sort
        } else if (algorithm == "quick") {
// quick sort
        } else if (algorithm == "merge") {
// merge sort
        }
// Edit here when adding a new algorithm
    }
};

Solution: Strategy Pattern encapsulates the algorithm so that it can be replaced at runtime. 다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// Good example: Strategy Pattern
// 타입 정의
class SortStrategy {
public:
    virtual void sort(std::vector<int>& data) = 0;
    virtual ~SortStrategy() = default;
};
class BubbleSort : public SortStrategy {
    void sort(std::vector<int>& data) override { /* ....*/ }
};
class Sorter {
public:
    void setStrategy(std::unique_ptr<SortStrategy> s) {
        strategy = std::move(s);
    }
    
    void sort(std::vector<int>& data) {
        strategy->sort(data);
    }
    
private:
    std::unique_ptr<SortStrategy> strategy;
};

아래 코드는 mermaid를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// 실행 예제
flowchart TD
    context["Context (Sorter)"]
    strategy["Strategy (SortStrategy)"]
    bubble[BubbleSort]
    quick[QuickSort]
    merge[MergeSort]
    
    context --> strategy
    strategy <|-- bubble
    strategy <|-- quick
    strategy <|-- merge

index

  1. Basic structure (polymorphic)
  2. Function pointer method
  3. Lambda method
  4. std::function method
  5. Frequently occurring problems and solutions
  6. Production Patterns
  7. Complete example: Compression algorithm
  8. Performance comparison

1. Basic structure (polymorphism)

Minimum Strategy

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class SortStrategy {
public:
    virtual void sort(std::vector<int>& data) = 0;
    virtual std::string name() const = 0;
    virtual ~SortStrategy() = default;
};
class BubbleSort : public SortStrategy {
public:
    void sort(std::vector<int>& data) override {
        for (size_t i = 0; i < data.size(); ++i) {
            for (size_t j = 0; j < data.size() - i - 1; ++j) {
                if (data[j] > data[j + 1]) {
                    std::swap(data[j], data[j + 1]);
                }
            }
        }
    }
    
    std::string name() const override { return "BubbleSort"; }
};
class QuickSort : public SortStrategy {
public:
    void sort(std::vector<int>& data) override {
        std::sort(data.begin(), data.end());
    }
    
    std::string name() const override { return "QuickSort"; }
};
class Sorter {
public:
    void setStrategy(std::unique_ptr<SortStrategy> s) {
        strategy = std::move(s);
    }
    
    void sort(std::vector<int>& data) {
        if (strategy) {
            std::cout << "Using " << strategy->name() << '\n';
            strategy->sort(data);
        }
    }
    
private:
    std::unique_ptr<SortStrategy> strategy;
};
int main() {
    Sorter sorter;
    std::vector<int> data = {5, 2, 8, 1, 9};
    
    sorter.setStrategy(std::make_unique<BubbleSort>());
    sorter.sort(data);  // Using BubbleSort
    
    sorter.setStrategy(std::make_unique<QuickSort>());
    sorter.sort(data);  // Using QuickSort
}

2. function pointer method

Simple algorithm

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <iostream>
#include <vector>
#include <algorithm>
using SortFunc = void(*)(std::vector<int>&);
void bubbleSort(std::vector<int>& data) {
    for (size_t i = 0; i < data.size(); ++i) {
        for (size_t j = 0; j < data.size() - i - 1; ++j) {
            if (data[j] > data[j + 1]) {
                std::swap(data[j], data[j + 1]);
            }
        }
    }
}
void quickSort(std::vector<int>& data) {
    std::sort(data.begin(), data.end());
}
class Sorter {
public:
    void setStrategy(SortFunc func) {
        strategy = func;
    }
    
    void sort(std::vector<int>& data) {
        if (strategy) {
            strategy(data);
        }
    }
    
private:
    SortFunc strategy = nullptr;
};
int main() {
    Sorter sorter;
    std::vector<int> data = {5, 2, 8, 1, 9};
    
    sorter.setStrategy(bubbleSort);
    sorter.sort(data);
    
    sorter.setStrategy(quickSort);
    sorter.sort(data);
}

3. lambda method

Inline Algorithm

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
class Sorter {
public:
    using Strategy = std::function<void(std::vector<int>&)>;
    
    void setStrategy(Strategy s) {
        strategy = s;
    }
    
    void sort(std::vector<int>& data) {
        if (strategy) {
            strategy(data);
        }
    }
    
private:
    Strategy strategy;
};
int main() {
    Sorter sorter;
    std::vector<int> data = {5, 2, 8, 1, 9};
    
// Define Strategy with lambda
    sorter.setStrategy( {
        std::sort(data.begin(), data.end());
    });
    sorter.sort(data);
    
// Sort in reverse order
    sorter.setStrategy( {
        std::sort(data.begin(), data.end(), std::greater<>());
    });
    sorter.sort(data);
}

4. std::function method

Flexible Strategy

다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
class PaymentStrategy {
public:
    using Strategy = std::function<bool(double)>;
    
    void setStrategy(Strategy s) {
        strategy = s;
    }
    
    bool pay(double amount) {
        if (strategy) {
            return strategy(amount);
        }
        return false;
    }
    
private:
    Strategy strategy;
};
int main() {
    PaymentStrategy payment;
    
// credit card
    payment.setStrategy( {
        std::cout << "Paying $" << amount << " with Credit Card\n";
        return true;
    });
    payment.pay(100.0);
    
    // PayPal
    payment.setStrategy( {
        std::cout << "Paying $" << amount << " with PayPal\n";
        return true;
    });
    payment.pay(50.0);
}

5. Frequently occurring problems and solutions

Problem 1: Strategy nullptr

Symptom: Crash. Cause: Strategy is not set. 아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Misuse: No nullptr check
void sort(std::vector<int>& data) {
    strategy->sort(data);  // Crash: nullptr
}
// ✅ Correct usage: nullptr check
void sort(std::vector<int>& data) {
    if (strategy) {
        strategy->sort(data);
    } else {
        throw std::runtime_error("Strategy not set");
    }
}

Problem 2: State sharing

Symptom: Behavior different from expected. Cause: If Strategy has state, it becomes problematic when reused. 다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// ❌ Misuse: state sharing
class CountingSort : public SortStrategy {
int count = 0;  // situation
public:
    void sort(std::vector<int>& data) override {
++count;  // Accumulation when reused
    }
};
// ✅ Correct use: Stateless Strategy
class CountingSort : public SortStrategy {
public:
    void sort(std::vector<int>& data) override {
// no state, pure algorithm
    }
};

6. production pattern

Pattern 1: Basic Strategy

다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

class Sorter {
public:
Sorter() : strategy(std::make_unique<QuickSort>()) {} // default value
    
    void setStrategy(std::unique_ptr<SortStrategy> s) {
        if (s) {
            strategy = std::move(s);
        }
    }
    
    void sort(std::vector<int>& data) {
strategy->sort(data);  // always valid
    }
    
private:
    std::unique_ptr<SortStrategy> strategy;
};

Pattern 2: Strategy Factory

아래 코드는 cpp를 사용한 구현 예제입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

class StrategyFactory {
public:
    static std::unique_ptr<SortStrategy> create(const std::string& type) {
        if (type == "bubble") return std::make_unique<BubbleSort>();
        if (type == "quick") return std::make_unique<QuickSort>();
        return nullptr;
    }
};
int main() {
    Sorter sorter;
    sorter.setStrategy(StrategyFactory::create("quick"));
}

7. Complete Example: Compression Algorithm

#include <iostream>
#include <string>
#include <memory>
#include <vector>
class CompressionStrategy {
public:
    virtual std::vector<uint8_t> compress(const std::string& data) = 0;
    virtual std::string decompress(const std::vector<uint8_t>& data) = 0;
    virtual std::string name() const = 0;
    virtual ~CompressionStrategy() = default;
};
class ZipCompression : public CompressionStrategy {
public:
    std::vector<uint8_t> compress(const std::string& data) override {
        std::cout << "[ZIP] Compressing " << data.size() << " bytes\n";
        std::vector<uint8_t> result(data.begin(), data.end());
        return result;
    }
    
    std::string decompress(const std::vector<uint8_t>& data) override {
        std::cout << "[ZIP] Decompressing " << data.size() << " bytes\n";
        return std::string(data.begin(), data.end());
    }
    
    std::string name() const override { return "ZIP"; }
};
class GzipCompression : public CompressionStrategy {
public:
    std::vector<uint8_t> compress(const std::string& data) override {
        std::cout << "[GZIP] Compressing " << data.size() << " bytes\n";
        std::vector<uint8_t> result(data.begin(), data.end());
        return result;
    }
    
    std::string decompress(const std::vector<uint8_t>& data) override {
        std::cout << "[GZIP] Decompressing " << data.size() << " bytes\n";
        return std::string(data.begin(), data.end());
    }
    
    std::string name() const override { return "GZIP"; }
};
class Compressor {
public:
    void setStrategy(std::unique_ptr<CompressionStrategy> s) {
        strategy = std::move(s);
    }
    
    std::vector<uint8_t> compress(const std::string& data) {
        if (!strategy) {
            throw std::runtime_error("Compression strategy not set");
        }
        std::cout << "Using " << strategy->name() << " compression\n";
        return strategy->compress(data);
    }
    
    std::string decompress(const std::vector<uint8_t>& data) {
        if (!strategy) {
            throw std::runtime_error("Compression strategy not set");
        }
        return strategy->decompress(data);
    }
    
private:
    std::unique_ptr<CompressionStrategy> strategy;
};
int main() {
    Compressor compressor;
    std::string data = "Hello, World! This is a test.";
    
    compressor.setStrategy(std::make_unique<ZipCompression>());
    auto compressed = compressor.compress(data);
    auto decompressed = compressor.decompress(compressed);
    std::cout << "Result: " << decompressed << "\n\n";
    
    compressor.setStrategy(std::make_unique<GzipCompression>());
    compressed = compressor.compress(data);
    decompressed = compressor.decompress(compressed);
    std::cout << "Result: " << decompressed << '\n';
}

8. Performance comparison

methodAdvantagesDisadvantages
polymorphismType safe, extensiblevtable overhead, heap allocation
Function pointerFast, simpleLack of type safety, no condition
LambdaInline, Capture CapableComplex type, difficult to debug
std::functionFlexible, all callableLarge overhead, heap allocation

organize

conceptDescription
Strategy PatternRuntime replacement by encapsulating algorithms
PurposeAlgorithm independence, scalability
StructureContext, Strategy, ConcreteStrategy
AdvantagesOCP compliance, removal of conditional statements, easy testing
Disadvantagesclass increment, indirect reference
Use CaseSorting, Compression, Payment, Routing
The Strategy Pattern is a powerful design pattern for situations where algorithms need to be replaced dynamically.

FAQ

Q1: When do I use Strategy Pattern?

A: Used when you need to choose between multiple algorithms and replace them at runtime.

Q2: Polymorphism vs Lambda?

A: If scalability is important, use polymorphism, and if simple algorithm, use lambda.

Q3: What is the difference from State Pattern?

A: Strategy focuses on algorithm replacement, State focuses on state transition.

Q4: What is the performance overhead?

A: Polymorphism has vtable lookup, std::function has heap allocation overhead. Function pointers are the fastest.

Q5: How do I set the basic Strategy?

A: Set the default Strategy in the constructor.

Q6: What are Strategy Pattern learning resources?

A:

  • “Design Patterns” by Gang of Four
  • “Head First Design Patterns” by Freeman & Freeman
  • Refactoring Guru: Strategy Pattern One line summary: Strategy Pattern allows you to encapsulate algorithms and replace them at runtime. Next, it would be a good idea to read Command Pattern.

Good article to read together (internal link)

Here’s another article related to this topic.

Practical tips

These are tips that can be applied right away in practice.

Debugging tips

  • If you run into a problem, check the compiler warnings first.
  • Reproduce the problem with a simple test case

Performance Tips

  • Don’t optimize without profiling
  • Set measurable indicators first

Code review tips

  • Check in advance for areas that are frequently pointed out in code reviews.
  • Follow your team’s coding conventions

Practical checklist

This is what you need to check when applying this concept in practice.

Before writing code

  • Is this technique the best way to solve the current problem?
  • Can team members understand and maintain this code?
  • Does it meet the performance requirements?

Writing code

  • Have you resolved all compiler warnings?
  • Have you considered edge cases?
  • Is error handling appropriate?

When reviewing code

  • Is the intent of the code clear?
  • Are there enough test cases?
  • Is it documented? Use this checklist to reduce mistakes and improve code quality.

Keywords covered in this article (related search terms)

This article will be helpful if you search for C++, strategy, pattern, algorithm, polymorphism, lambda, etc.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3