- 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();
}
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;
}