State_Pattern_2 - 8BitsCoding/RobotMentor GitHub Wiki

목차

  • Fun with Finite(한정된) State Machines.
  • A pattern in which the object's behavior is determined by its state.
  • An object transitions from one state to another
  • A formalized construct which manages state and transitions is called a state machine.

Classic State Implementation

struct State
{
    virtual void on(Lightswitch* ls)
    {
        cout << "Light is already on \n";
    }

    virtual void off(Lightswitch* ls)
    {
        cout << "Light is already off \n";
    }
};

struct Onstate : State
{
    Onstate()
    {
        cout << "Light is turned on\n";
    }


};

struct OffState : State
{
    OffState()
    {
        cout << "Light is turned off\n";
    }

};

class Lightswitch
{
    State * state;
public:
    Lightswitch()
    {
        state = new OffState();
    }

    void set_state(State* state)
    {
        this->state = state;
    }

    void on() {
        state->on(this);
    }
    void off() {
        state->off(this);
    }
}

void Onstate::off(Lightswitch* ls) override
{
    cout << "Swithcing light off...\n";
    ls->set_state(new OffState());
    delete this;
}

void OffState::on(Lightswitch* ls) override
{
    cout << "Swithcing light on...\n";
    ls->set_state(new OnState());
    delete this;
}

int main()
{
    LightSwitch ls;
    ls.on();
    ls.off();
    ls.off();

    return 0;
}
    

Classic State Implementation 전체코드

#include <iostream>
#include <string>
using namespace std;

class LightSwitch;

struct State
{
  virtual void on(LightSwitch *ls)
  {
    cout << "Light is already on\n";
  }
  virtual void off(LightSwitch *ls)
  {
    cout << "Light is already off\n";
  }
};

struct OnState : State
{
  OnState()
  {
    cout << "Light turned on\n";
  }

  void off(LightSwitch* ls) override;
};

struct OffState : State
{
  OffState()
  {
    cout << "Light turned off\n";
  }

  void on(LightSwitch* ls) override;
};

class LightSwitch
{
  State *state;
public:
  LightSwitch()
  {
    state = new OffState();
  }
  void set_state(State* state)
  {
    this->state = state;
  }
  void on() { state->on(this); }
  void off() { state->off(this); }
};

void OnState::off(LightSwitch* ls)
{
  cout << "Switching light off...\n";
  ls->set_state(new OffState());
  delete this;
}

void OffState::on(LightSwitch* ls)
{
  cout << "Switching light on...\n";
  ls->set_state(new OnState());
  delete this;
}

void main_3()
{
  LightSwitch ls;
  ls.on();
  ls.off();
  ls.off();
  getchar();
}

Handmade State Machine

enum class State
{
    off_hook,
    connecting,
    connected,
    on_hold,
    on_hook
};

inline ostream& operator<<(ostream& os, const State& s)
{
  switch (s)
  {
  case State::OffHook:
    os << "off the hook";
    break;
  case State::Connecting:
    os << "connecting";
    break;
  case State::Connected: 
    os << "connected";
    break;
  case State::OnHold:
    os << "on hold";
    break;
  case State::OnHook:
    os << "on the hook";
    break;
  }
  return os;
}

enum class Trigger
{
    call_dialed,
    hung_up,
    call_connected,
    placed_on_hold,
    taken_off_hold,
    left_message,
    stop_using_phone
};

inline ostream& operator<<(ostream& os, const Trigger& t)
{
  switch (t)
  {
  case Trigger::CallDialed:
    os << "call dialed";
    break;
  case Trigger::HungUp:
    os << "hung up";
    break;
  case Trigger::CallConnected:
    os << "call connected";
    break;
  case Trigger::PlacedOnHold:
    os << "placed on hold";
    break;
  case Trigger::TakenOffHold:
    os << "taken off hold";
    break;
  case Trigger::LeftMessage: 
    os << "left message";
    break;
  case Trigger::StopUsingPhone:
    os << "putting phone on hook";
    break;
  default: break;
  }
  return os;
}

int main()
{
    map<State, vector<pair<Trigger, State>>> rules;
    rules[State::off_hook] = {
        {Trigger::call_dialed, State::connecting},
        {Trigger::stop_using_phone, State::on_hook}
    };

    rules[State::Connecting] = {
        {Trigger::HungUp, State::OffHook},
        {Trigger::CallConnected, State::Connected}
    };

    rules[State::Connected] = {
        {Trigger::LeftMessage, State::OffHook},
        {Trigger::HungUp, State::OffHook},
        {Trigger::PlacedOnHold, State::OnHold}
    };

    rules[State::OnHold] = {
        {Trigger::TakenOffHold, State::Connected},
        {Trigger::HungUp, State::OffHook}
    };

    State currentState{ State::OffHook },
            exitState{ State::OnHook };

    return 0;
}

Handmade State Machine 전체코드

#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;

enum class State
{
  OffHook,
  Connecting,
  Connected,
  OnHold,
  OnHook
};

inline ostream& operator<<(ostream& os, const State& s)
{
  switch (s)
  {
  case State::OffHook:
    os << "off the hook";
    break;
  case State::Connecting:
    os << "connecting";
    break;
  case State::Connected: 
    os << "connected";
    break;
  case State::OnHold:
    os << "on hold";
    break;
  case State::OnHook:
    os << "on the hook";
    break;
  }
  return os;
}

enum class Trigger
{
  CallDialed,
  HungUp,
  CallConnected,
  PlacedOnHold,
  TakenOffHold,
  LeftMessage,
  StopUsingPhone
};

inline ostream& operator<<(ostream& os, const Trigger& t)
{
  switch (t)
  {
  case Trigger::CallDialed:
    os << "call dialed";
    break;
  case Trigger::HungUp:
    os << "hung up";
    break;
  case Trigger::CallConnected:
    os << "call connected";
    break;
  case Trigger::PlacedOnHold:
    os << "placed on hold";
    break;
  case Trigger::TakenOffHold:
    os << "taken off hold";
    break;
  case Trigger::LeftMessage: 
    os << "left message";
    break;
  case Trigger::StopUsingPhone:
    os << "putting phone on hook";
    break;
  default: break;
  }
  return os;
}

int main_f(char* argv[])
{
  map<State, vector<pair<Trigger, State>>> rules;

  rules[State::OffHook] = {
    {Trigger::CallDialed, State::Connecting},
    {Trigger::StopUsingPhone, State::OnHook}
  };

  rules[State::Connecting] = {
    {Trigger::HungUp, State::OffHook},
    {Trigger::CallConnected, State::Connected}
  };

  rules[State::Connected] = {
    {Trigger::LeftMessage, State::OffHook},
    {Trigger::HungUp, State::OffHook},
    {Trigger::PlacedOnHold, State::OnHold}
  };

  rules[State::OnHold] = {
    {Trigger::TakenOffHold, State::Connected},
    {Trigger::HungUp, State::OffHook}
  };

  State currentState{ State::OffHook },
        exitState{ State::OnHook };

  while (true)
  {
    cout << "The phone is currently " << currentState << endl;
  select_trigger:
    cout << "Select a trigger:" << "\n";

    int i = 0;
    for (auto item : rules[currentState])
    {
      cout << i++ << ". " << item.first << "\n";
    }

    int input;
    cin >> input;
    if (input < 0 || (input+1) > rules[currentState].size())
    {
      cout << "Incorrect option. Please try again." << "\n";
      goto select_trigger;
    }

    currentState = rules[currentState][input].second;
    if (currentState == exitState) break;
  }

  cout << "We are done using the phone" << "\n";

  getchar();
  getchar();
  return 0;
}
⚠️ **GitHub.com Fallback** ⚠️