State - shoonie/StudyingDesignPattern GitHub Wiki
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
- It localizes state-specific behavior and partitions behavior for different states.
- It makes state transitions explicit.
- State objects can be shared.
- Who defines the state transitions?
- A table-based alternative.
- Creating and destroying State objects.
- Using dynamic inheritance.
//https://www.robertlarsononline.com/2017/05/11/state-pattern-using-cplusplus/
#include <iostream>
namespace MusicPlayerSample
{
enum State
{
ST_STOPPED,
ST_PLAYING,
ST_PAUSED
};
class AbstractMusicPlayer {
public:
virtual void SetState(State state) = 0;
};
class MusicPlayerState {
public:
MusicPlayerState(std::string name) : m_name(name)
{
}
virtual ~MusicPlayerState() {}
virtual void Play(AbstractMusicPlayer * player) {
std::cout << "Illegal state transition from "
<< GetName() << " to Playing\n";
}
virtual void Pause(AbstractMusicPlayer * player) {
std::cout << "Illegal state transition from "
<< GetName() << " to Paused\n";
}
virtual void Stop(AbstractMusicPlayer * player) {
std::cout << "Illegal state transition from "
<< GetName() << " to Stopped\n";
}
std::string GetName() { return m_name; }
private:
std::string m_name;
};
class PlayingState : public MusicPlayerState {
public:
PlayingState() : MusicPlayerState(std::string("Playing"))
{
}
virtual ~PlayingState() {}
virtual void Pause(AbstractMusicPlayer * player) {
player->SetState(ST_PAUSED);
}
virtual void Stop(AbstractMusicPlayer * player) {
player->SetState(ST_STOPPED);
}
};
class PausedState : public MusicPlayerState {
public:
PausedState() : MusicPlayerState(std::string("Paused"))
{
}
virtual ~PausedState()
{}
virtual void Play(AbstractMusicPlayer * player)
{
player->SetState(ST_PLAYING);
}
virtual void Stop(AbstractMusicPlayer * player)
{
player->SetState(ST_STOPPED);
}
};
class StoppedState : public MusicPlayerState {
public:
StoppedState() : MusicPlayerState(std::string("Stopped"))
{
}
virtual ~StoppedState() {}
virtual void Play(AbstractMusicPlayer * player) {
player->SetState(ST_PLAYING);
}
};
class MusicPlayer :public AbstractMusicPlayer
{
public:
MusicPlayer() : m_pState(new StoppedState())
{}
virtual ~MusicPlayer() {
if (m_pState != nullptr)
delete m_pState;
}
void Play() {
m_pState->Play(this);
}
void Pause() {
m_pState->Pause(this);
}
void Stop() {
m_pState->Stop(this);
}
void SetState(State state);
private:
MusicPlayerState * m_pState;
};
void MusicPlayer::SetState(State state)
{
std::cout << "changing from " << m_pState->GetName() << " to ";
delete m_pState;
if (state == ST_STOPPED)
{
m_pState = new StoppedState();
}
else if (state == ST_PLAYING)
{
m_pState = new PlayingState();
}
else
{
m_pState = new PausedState();
}
std::cout << m_pState->GetName() << " state\n";
}
}
int main()
{
MusicPlayerSample::MusicPlayer player;
player.Play();
player.Pause();
player.Stop();
return 0;
}