Strategy Pattern

 Comparison of Modern C++ Approaches

Implementation TypeMechanismResolution TimeMemory OverheadUse Case
Runtime (Functional)std::function & LambdasRuntimeSmall heap allocation (if lambda captures exceed small-buffer optimization)When algorithms must change on the fly during program execution.
Compile-time (Static)Templates & Concepts (requires)Compile-timeZero runtime overhead (inlines perfectly)High-performance systems where strategies are known at compile time.

Example 1:
#include <bits/stdc++.h>
class SortingStrategy {
public:
    virtual void sort(std::vector<int>& arr) = 0;
};
class BubbleSort : public SortingStrategy {
public:
    void sort(std::vector<int>& arr) override
    {
        // Implement Bubble Sort algorithm
    }
};

class QuickSort : public SortingStrategy {
public:
    void sort(std::vector<int>& arr) override
    {
        // Implement Quick Sort algorithm
    }
};

// Add more sorting algorithms as needed

class SortContext {
private:
    SortingStrategy* strategy;

public:
    void setStrategy(SortingStrategy* strategy)
    {
        this->strategy = strategy;
    }

    void executeStrategy(std::vector<int>& arr)
    {
        strategy->sort(arr);
    }
};
int main()
{
    std::vector<int> data = { 5, 2, 7, 1, 9 };

    SortContext context;
    BubbleSort bubbleSort;
    QuickSort quickSort;

    context.setStrategy(&bubbleSort);
    context.executeStrategy(data); // Executes Bubble Sort

    context.setStrategy(&quickSort);
    context.executeStrategy(data); // Executes Quick Sort

    return 0;
}
Example 2:
#include <iostream>
#include <iostream>
#include <functional>
#include <string_view>
#include <vector>

// The Context class expects a callable strategy
class TextFormatter {
private:
    // Type-erase the formatting strategy using std::function
    std::function<void(std::string_view)> strategy_;

public:
    // Explicit constructor accepts any matching callable
    explicit TextFormatter(std::function<void(std::string_view)> strategy) 
        : strategy_(std::move(strategy)) {}

    // Allows dynamic swapping of strategies at runtime
    void set_strategy(std::function<void(std::string_view)> strategy) {
        strategy_ = std::move(strategy);
    }

    void format(std::string_view text) const {
        if (strategy_) {
            strategy_(text);
        }
    }
};

int main() {
    // Concrete strategies defined cleanly as inline lambdas
    auto markdown_strategy = [](std::string_view text) {
        std::cout << "**" << text << "**\n";
    };

    auto html_strategy = [](std::string_view text) {
        std::cout << "<p>" << text << "</p>\n";
    };

    // Client usage
    TextFormatter formatter(markdown_strategy);
    formatter.format("Hello Modern C++"); // Output: **Hello Modern C++**

    // Swap strategy at runtime
    formatter.set_strategy(html_strategy);
    formatter.format("Hello Modern C++"); // Output: <p>Hello Modern C++</p>
}
Example 3:
#include <iostream>
#include <concepts>
#include <string_view>

// Define a C++20 Concept to enforce the strategy interface at compile time
template <typename T>
concept CompressionStrategy = requires(T strategy, std::string_view data) {
    { strategy.compress(data) } -> std::same_as<void>;
};

// Concrete Strategy A
class ZipCompression {
public:
    void compress(std::string_view data) const {
        std::cout << "Compressing '" << data << "' using ZIP algorithm.\n";
    }
};

// Concrete Strategy B
class RarCompression {
public:
    void compress(std::string_view data) const {
        std::cout << "Compressing '" << data << "' using RAR algorithm.\n";
    }
};

// The Context class uses template parameters constrained by our concept
template <CompressionStrategy Strategy>
class CompressionContext {
private:
    Strategy strategy_; // Embedded by value, no pointer chasing/indirection

public:
    // Default or explicit constructor
    CompressionContext() = default;
    explicit CompressionContext(Strategy strategy) : strategy_(std::move(strategy)) {}

    void create_archive(std::string_view data) const {
        // Core framework logic goes here...
        strategy_.compress(data);
    }
};

int main() {
    // Strategy is bound at compile time; compiler can aggressively inline the calls
    CompressionContext<ZipCompression> zip_archive;
    zip_archive.create_archive("ProjectFiles");

    CompressionContext<RarCompression> rar_archive;
    rar_archive.create_archive("BackupData");
    
    // CompressionContext<int> broken; // Compilation error: int does not satisfy CompressionStrategy
}

Comments

Popular posts from this blog

BdsDex: failed to load Boot0001 "UEFI BHYVE SATA DISK BHYVE-OABE-20A5-E582" from PciRoot(0x0)/Pci (0x2, 0x0)/Stat(0x0,0xFFFF,0x0) : Not Found

FFmpeg