// FSM_DEM1.CPP // Finite State Machine (FSM) implementation of Elevator Simulation // Design notes for machine type #1 // ================================ // example developed in "Object Oriented State Machines", // Ted Faison, Software Development, Sep 1993, pg 36 // Base class provides interface for all states which: // define events - action defaults to no state transition // report state to user - default to invalid // Derived classes: // Each derived class represents a state and is responsible for // deleting itself and creating next state // Derived class redefines event processing appropriate for // it's state transitions. // The way it works: // - The client creates the first state in dynamic (heap) memory. // From then on, when a state makes a transition it deletes // itself and creates the next state on the heap. // - The client starts the machine by starting up an event loop. // Each state passes back a pointer to its next state when it // completes processing. // Cautions: // Member functions change state by deleting themselves and // creating the next state on the heap. Objects should never // delete their own "this" pointer unless they've been // constructed on the heap. /* */ // Define states and state processing with class hierarchy // ======================================================= class ElevState { public: virtual ~ElevState() {} virtual ElevState* UPbutton() { return this; } virtual ElevState* DOWNbutton() { return this; } virtual ElevState* Arrived() { return this; } virtual char* Description() { return "Invalid State"; } }; class StateOnFirstFloor: public ElevState { public: ElevState* UPbutton(); char* Description() { return "on first floor"; } }; class StateGoingUp: public ElevState { public: ElevState* Arrived(); char* Description() { return "going up"; } }; class StateOnSecondFloor: public ElevState { public: ElevState* DOWNbutton(); char* Description() { return "on second floor"; } }; class StateGoingDown: public ElevState { public: ElevState* Arrived(); char* Description() { return "going down"; } }; // Define state processing // ======================= ElevState* StateOnFirstFloor::UPbutton() { delete this; return new StateGoingUp; } ElevState* StateGoingUp::Arrived() { delete this; return new StateOnSecondFloor; } ElevState* StateOnSecondFloor::DOWNbutton() { delete this; return new StateGoingDown; } ElevState* StateGoingDown::Arrived() { delete this; return new StateOnFirstFloor; } /* */ // Define events and event processing // ================================== #include void PromptForNextEvent(ElevState& state, int& event) { cout << "\n\nCurrent state = " << state.Description() << endl; cout << "Event types:" << endl << "1 - UP button" << endl << "2 - Arrived at floor" << endl << "3 - DOWN button" << endl << "enter next event type "; cin >> event; } ElevState* ProcessNextEvent(ElevState& state, int event) { const int UPbutton = 1, Arrived = 2, DOWNbutton = 3; switch(event) { case UPbutton : return state.UPbutton(); case Arrived : return state.Arrived(); case DOWNbutton : return state.DOWNbutton(); default : return 0; } } void main() { // construct start state ElevState* currentState = new StateOnFirstFloor; // start machine's event loop do { int event; PromptForNextEvent(*currentState, event); currentState = ProcessNextEvent(*currentState, event); } while (currentState); delete currentState; }