State Design Pattern in C++ for a Music System

State Design pattern allows an object to change it's behavior based on its internal State.The Object will appear to change its class.
State Design Pattern in C++ to implement state machine of a Music Player System.
classes used:
MusicSystem -> is the current state context manager class.
State -> is the base class of all states classes.
OFFState -> is the concrete class derived from State.
ONState -> is the concrete class derived from State.
PAUSEDState ->is the concrete class derived from State.
Example:
#include<iostream>
using namespace std;

//current_context class
class State;
class MusicSystem
{
private:
    State *currentState;//to store current state.
   
public:
    enum statesEnum
        {
        ST_STOPPED,
        ST_PLAYING,
        ST_PAUSEDState
        };
public:
    MusicSystem();

    void stopMusic();
    void playMusic();
    void playNextTrack();
    void playPreviousTrack();
    void pauseMusic();
    void setCurrentContext(statesEnum state);
};

//abstract state class
class State
{
public:
    //MusicSystem's pointer is passed so that setCurrentState can be called.
    virtual void off(MusicSystem *ms){cout<<"Already Stopped."<<endl;}
    virtual void play(MusicSystem* ms){cout<<"Already Playing."<<endl;}
    virtual void playNextTrack(MusicSystem* ms){cout<<"Can not play Next in off/paused state."<<endl;}
    virtual void playPreviousTrack(MusicSystem* ms){cout<<"Can not play Previous in off/paused state."<<endl;}
    virtual void pause(MusicSystem* ms){cout<<"Can not Switch to pause in stopped state."<<endl;}
};
//concrete state class on
class OFFState:public State
{
public:
    void play(MusicSystem *ms);
};

//concrete state class off
class ONState:public State
{
public:
    void off(MusicSystem *ms);
    void playNextTrack(MusicSystem *ms);
    void playPreviousTrack(MusicSystem *ms);
    void pause(MusicSystem* ms);
};
//concrete class pause
class PAUSEDState:public State
{
public:
    void off(MusicSystem *ms);
    void playNextTrack(MusicSystem *ms);
    void playPreviousTrack(MusicSystem *ms);
    void play(MusicSystem* ms);
   
};

MusicSystem::MusicSystem()
{
    currentState=new OFFState;
}
void MusicSystem::stopMusic()
{
    currentState->off(this);  
}
void MusicSystem::playMusic()
{
    currentState->play(this);  
}
void MusicSystem::playNextTrack()
{
    currentState->playNextTrack(this);  
}
void MusicSystem::playPreviousTrack()
{
    currentState->playPreviousTrack(this);  
}
void MusicSystem::pauseMusic()
{
    currentState->pause(this);
}


    void OFFState::play(MusicSystem *ms)
    {
    cout<<"Turning to Play."<<endl;
    ms->setCurrentContext(MusicSystem::ST_PLAYING);
    delete this;
    }
    void ONState::off(MusicSystem *ms)
    {
    cout<<"Turning to Stopped."<<endl;
    ms->setCurrentContext(MusicSystem::ST_STOPPED);
    delete this;
    }
    void ONState::playNextTrack(MusicSystem *ms)
    {
    cout<<"Playing next track..."<<endl;
    }
    void ONState::playPreviousTrack(MusicSystem *ms)
    {
    cout<<"Playing previous track..."<<endl;
    }
    void ONState::pause(MusicSystem* ms)
    {
    cout<<"Switching to Pause."<<endl;   
    ms->setCurrentContext(MusicSystem::ST_PAUSEDState);
    }
   
    void PAUSEDState::off(MusicSystem *ms)
    {
    cout<<"Turning to Stopped."<<endl;
    ms->setCurrentContext(MusicSystem::ST_STOPPED);
    delete this;
    }
    void PAUSEDState::playNextTrack(MusicSystem *ms)
    {
    cout<<"Playing next track..."<<endl;
    }
    void PAUSEDState::playPreviousTrack(MusicSystem *ms)
    {
    cout<<"Playing previous track..."<<endl;
    }
    void PAUSEDState::play(MusicSystem* ms)
    {
    cout<<"Switching to Play."<<endl;   
    ms->setCurrentContext(MusicSystem::ST_PLAYING);
    }


void MusicSystem::setCurrentContext(statesEnum state)
    {
        if(state==ST_STOPPED)
    {
    currentState=new OFFState;
    }
    else if(state == ST_PLAYING)
    {
    currentState=new ONState();
    }
    else if(state == ST_PAUSEDState)
    {
    currentState=new PAUSEDState();
    }
    else
    {
    cout<<"Unknown state"<<endl;
    }
    }


//main
int main()
{
MusicSystem ms;

ms.MusicSystem::stopMusic();
ms.MusicSystem::stopMusic();
ms.MusicSystem::pauseMusic();
ms.MusicSystem::playNextTrack();
ms.MusicSystem::playPreviousTrack();

ms.MusicSystem::playMusic();
ms.MusicSystem::playMusic();
ms.MusicSystem::pauseMusic();
ms.MusicSystem::playNextTrack();
ms.MusicSystem::playPreviousTrack();

ms.MusicSystem::stopMusic();
ms.MusicSystem::playNextTrack();
ms.MusicSystem::playPreviousTrack();

return 0;
}
/*
Already Stopped.
Already Stopped.
Can not Switch to pause in stopped state.
Can not play Next in off/paused state.
Can not play Previous in off/paused state.
Turning to Play.
Already Playing.
Switching to Pause.
Playing next track...
Playing previous track...
Turning to Stopped.
Can not play Next in off/paused state.
Can not play Previous in off/paused state.
*/

No comments:

Post a Comment