How to use Strategy Pattern Instead of Switch-Case statements

21 05 2013


Cyclomatic complexity or conditional complexity is the term used in software module to measure the amount of decision points(logic) in our code. It would be better to keep minimum Cyclomatic complexity within the method level for better code readability and adhere to OOP principles. Incase if there is a switch-case statements in our method, corresponding to each case statement it increases the code complexity by one. So how we can avoid it.


The answer is, switch-case statements can be replaced with Strategy Design pattern.

Problem – Please see below code snippet where a Media Player object is calling differnt methods based on the file extension.

enum eMediaPlayerType
{
    WMPlayer = 0,
    RMPlayer,
    FMPlayer
};

class CMediaPlayer
{
public:
    void PlayWMFile()
    {
    }

    void PlayRMFile()
    {
    }

    void PlayFMFile()
    {
    }
};

void PlayFileBasedOnExtension()
{

    //.WMV file
    eMediaPlayerType etype = WMPlayer;
    CMediaPlayer MediaPlayer; 

    switch (etype)
    {
    case WMPlayer:
        MediaPlayer.PlayWMFile();
        break;
    case RMPlayer:
        MediaPlayer.PlayRMFile();
        break;
    case FMPlayer:
        MediaPlayer.PlayFMFile();
        break;
    }
}

Replace Switch-Case with Strategy Pattern

class IMediaPlayer
{
public:
    virtual void Play() = 0;
};

class CWindowsMediaPlayer : public IMediaPlayer
{
public:
    void Play()
    {
    }
};

class CRealMediaPlayer : public IMediaPlayer
{
public:
    void Play()
    {
    }
};

class CFlashMediaPlayer : public IMediaPlayer
{
public:
    void Play()
    {
    }
};

void ReplaceSwitchWithStrategyPattern()
{
    map<eMediaPlayerType, IMediaPlayer*> Strategies;

    IMediaPlayer* pWMPlyer = new CWindowsMediaPlayer();
    Strategies[WMPlayer] = pWMPlyer;

    IMediaPlayer* pRMPlyer = new CRealMediaPlayer();
    Strategies[RMPlayer] = pRMPlyer;

    IMediaPlayer* pFMPlyer = new CFlashMediaPlayer();
    Strategies[FMPlayer] = pFMPlyer;

    /////// Change the player based on media file extension
    eMediaPlayerType etype = WMPlayer; //.WMV file
    map<eMediaPlayerType, IMediaPlayer*>::iterator itr = Strategies.find(etype);
    itr->second->Play();
}


Even though it reduce code complexity and follow OOP principle, it will force us to add more classes.