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.

Advertisements

Actions

Information

2 responses

19 07 2014
vaibhav

Hi,
Thanks for such a good example.
I really appreciate the efforts .
this is really a excellent site related to various good stuffs.

In this current example everything looks awesome.
but here is big memory leak in this function
ReplaceSwitchWithStrategyPattern
it would be nice if you could handle this memory leakage then this would become a perfect solution.

21 07 2014
Sanoop S P

Hello Vaibhav,

Thank you very much.
I will correct it as you suggested.

With Best Regards,
Sanoop

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: