behavioral

Strategy 

Purpose

Allows a family of algorithms to be defined while encapsulating each one. The algorithms can vary independently from clients using them.

UML

Behavior

The context forwards requests from its clients to its strategy: A client creates the context class and initializes it (through its constructor) with the required type of strategy. A client invokes a strategy method indirectly by calling a public method on the context object, which in turn calls the correct strategy method through its strategy data member (pStrategy in the UML diagram).

Example

The Strategy pattern is applied to creating different hashing algorithms. Each hashing algorithm is implemented differently in its own separate class. The Strategy pattern organizes this class hierarchy by allowing a client to be configured dynamically with the required hashing algorithm.

Usage

/* Strategy Classes */

/* Abstract Strategy */
class BaseHashStrategy 
{
// Constructors/Destructors
public:
    BaseHashStrategy() {}
    virtual ~BaseHashStrategy() {}

// public interface
public:
    virtual int GetHashValue( long lData )
    {
        // Base implementation comes here 
        std::cout << "In BaseHashStrategy::GetHashValue" << std::endl;
        return -1;
    }
};

/* Concrete Stategies */
class DivisionHashStrategy : public BaseHashStrategy 
{
    // Constructors/Destructors
public:
    DivisionHashStrategy() {}
    virtual ~DivisionHashStrategy() {}

    // public interface
public:
    int GetHashValue( long lData )
    { 
        // Division implementation comes here 
        OutputDebugString(" In DivisionHashStrategy::GetHashValue");
        return 1;
    }
};

class FibonacciHashStrategy : public BaseHashStrategy 
{
public:
    FibonacciHashStrategy() {}
    virtual ~FibonacciHashStrategy() {}

// public interface
public:
    int GetHashValue( long lData )
    {
        // Fibonannce implementation comes here
        OutputDebugString(" In FibonacciHashStrategy::GetHashValue");
        return 2;
    }
};

class MiddleSquareHashStrategy : public BaseHashStrategy 
{
public:
    MiddleSquareHashStrategy() {}
    virtual ~MiddleSquareHashStrategy() {}

// public interface
public:
    int GetHashValue( long lData )
    {
        // Middle Square implementation comes here ...
        OutputDebugString(" In MiddleSquareHashStrategy::GetHashValue");
    return 3;
    }
};

/* Context Class */

#include "BaseHashStrategy.h"
class CHash 
{
// Constructors/Destructors
public:
    CHash( BaseHashStrategy* pBHS ) : m_pBHS( pBHS ) {}
    virtual ~CHash() 
    { 
        delete m_pBHS;
        m_pBHS = NULL;
    }

// Public interface
    int CalculateHash( long lData)
    {
        /* Calls GetHashValue() in the class determined by the dynamic type
        of m_pBHS. Note that we chose to pass data between a strategy and its
        context class using parameters */
        return m_pBHS->GetHashValue( lData );
    }
private:
    /* Holds a reference to the required strategy class. Static type of m_pBHS
    is BaseHashStrategy but its dynamic type is that passed in by the client
    to CHash constructor Recall: dynamic type decided where virtuals are called */
    BaseHashStrategy *m_pBHS;
};

int main(int argc, char* argv[])
{
    CHash *pH = new CHash( new DivisionHashStrategy );
    int nRet = pH->CalculateHash( 1000 );            // calls DivisionHashStrategy::GetHashValue

    delete pH;
    return 0;
}

Notes