# Strategy

With strategy design pattern, it is possible do define a family of algorithms and choose the appropriate one to use at runtime. Since the algorithm is implemented in a separate class, it makes them interchangeable. 

Strategy design pattern uses composition approach. 

It separates the business logic of a class from the implementation details of algorithms (SRP). 

Adding a new algorithm won’t affect the client code (Open/Close Principle). 

## Structure 

![](https://mymakebucket1242.s3.eu-north-1.amazonaws.com/work/hashnode/7acc632a-85b3-4103-a6c7-c3b981d5876b/image-f0b9d713-6672-4178-8eca-340811cdc36f.png)

## Implementation 

### Classic Example (Dynamic) 

```
// Define the interface common to all supported versions of some algorithms
class Strategy {
public:
	virtual ~Strategy() = default;
	virtual std::string doAlgorithm(std::string_view data) const = 0;
}

class ConcreteStrategyA : public Strategy {
public:
	std::string doAlgorithm(std::string_view data) const override
	{
		std::string result(data);
		std::sort(std::begin(result), std::end(result));
		return result;
	}
}

class ConcreteStrategyB : public Strategy {
public:
	std::string doAlgorithm(std::string_view data) const override
	{
		std::string result(data);
		std::sort(std::begin(result), std::end(result), std::greater<>());
		return result;
	}
}

class Context
{
private:
	std::unique_ptr<Strategy> m_strategy;
	
public:
	explicit Context(std::unique_ptr<Strategy>&& strategy = {}): strategy_(std::move(strategy)) {}
	
	// ALternatively use factory pattern
	void set_strategy(std::unique_ptr<Strategy>&& strategy) {
		m_strategy = std::move(strategy);
	}
	
	void doSomething() const {
		if (m_strategy) {
			std::string result = m_strategy->doAlgorithm("abcde");
		} else {
			std::cout << "Context Strategy is not set
";
		}
	}
}

int main() {
	Context context(std::make_unique<ConcreteStrategyA>());
	context.doSomething();
} 

```

### Static Strategy (Template) 

If you want to avoid using vtable. 

```
template<typename LS>
struct TextProcessor {
    void append_list(const vector<string> &items) {
        m_list_strategy.start(m_oss);
        for (auto & item: items)
            m_list_strategy.add_list_item(m_oss, item);
        m_list_strategy.end(m_oss);
    }

    string str() const { return m_oss.str(); }
private:
    ostringstream       m_oss;
    LS                  m_list_strategy;
};

int main() {
    // markdown
    TextProcessor<MarkdownListStrategy> tp1;
    tp1.append_list({ "foo", "bar", "baz" });
    cout << tp1.str() << endl;

    // html
    TextProcessor<HtmlListStrategy> tp2;
    tp2.append_list({ "foo", "bar", "baz" });
    cout << tp2.str() << endl;

    return EXIT_SUCCESS;
} 

```

### Functional approach using Lambda 

The strategy can be implemented as an anonymous function instead. With this approach, we can avoid bloating the code with extra classes and interfaces 

## Credits 

[https://refactoring.guru/design-patterns/strategy](https://refactoring.guru/design-patterns/strategy) 

[https://vishalchovatiya.com/posts//strategy-design-pattern-in-modern-cpp/](https://vishalchovatiya.com/posts//strategy-design-pattern-in-modern-cpp/) 


