Design Patterns in C++: Strategy

Design Patterns in C++: Strategy

The Strategy Pattern allows you to change an algorithm at runtime. Image for example some algorithms to calculate the square root, as you may know there are plenty of it. They all do the same, but they all have their own upsides and downsides – one is more accurate, the other one is less expensive (computation time).

Normally, you have to choose your color at the beginning (at least at playing ludo) – right? So if you have decided for one algorithm – you have to keep it till the end.

But sometimes you need to change something at runtime, e.g. when your kid is noticing that he/she really really hates that ugly green the token has – the bluish one would be so much better!

Using the Strategy Pattern that is not a problem, as long as they have the same interface (shape, size, purpose in the sense of ludo).

// g++ -std=gnu++11 strategy.cpp -o strategy

#include <iostream>
#include <memory>

using namespace std;

// abstract base class
class Token {
public:
    // pure virtual function, derived classes have to implement it
    virtual void shout() = 0;

    virtual ~Token() {}
};

class GreenToken : public Token {
public:
    void shout() { cout << "ugly green, nobody ever won using green..." << endl; }
};

class BlueToken : public Token {
public:
    void shout() { cout << "oh what a wonderful blue, here we go!" << endl; }
};

class YellowToken : public Token {
public:
    void shout() { cout << "pff... yellow" << endl; }
};

class Player {
private:
    shared_ptr<Token> _strat;
    
public:
    Player() : _strat(nullptr) {}
    
    void setStrategy(shared_ptr<Token> strat) {
        cout << "changing strategy" << endl;
        _strat = strat;
    }
    
    void shout()  {
        if (_strat)
            (*_strat).shout();
    }
};

int main() {
    Player *kiddo = new Player();

    // create the tokens and store their references as shared_pointers
    shared_ptr<Token> green_token = make_shared<GreenToken>();
    shared_ptr<Token> blue_token = make_shared<BlueToken>();
    shared_ptr<Token> yellow_token = make_shared<YellowToken>();

    // try the green one
    kiddo->setStrategy(green_token);
    kiddo->shout();

    cout << green_token.use_count() << endl;

    // let's change to the blue one
    kiddo->setStrategy(blue_token);
    kiddo->shout();
}

We are using so-called smart pointers (e.g. shared_ptr<>) because the pointers to the tokens are shared between the main-routine, where they are created, and the Player() class.

In the example above a classic pointer would do the job too, but we are on the safe side if we use smart ones, since this way it does not matter if the code inside the strategy pattern does somehow delete the pointer or not – it just keeps alive as long as we need it.

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on print
Share on email