Headfirst设计模式的C++实现——状态模式(State)
state.h
1 #ifndef _STATE_H_ 2 #define _STATE_H_ 3 4 class GumballMachine; 5 6 class State { 7 public: 8 virtual void insert_quarter() = 0; 9 virtual void eject_quarter() = 0; 10 virtual void turn_crank() = 0; 11 virtual void dispense() = 0; 12 State( GumballMachine &_gumball_machine ) : gumball_machine (_gumball_machine ) {} 13 protected: 14 GumballMachine &gumball_machine; 15 }; 16 #endif
gumball_machine.h
说明:这里之所有要把SoldOutState等状态定义在GumballMachine类之中是因为两者之间有相互的依赖,暂时没有想到其他的解决方法。
1 #ifndef _GUMBALL_MACHINE_H_ 2 #define _GUMBALL_MACHINE_H_ 3 #include <iostream> 4 #include "state.h" 5 6 class GumballMachine { 7 private: 8 class SoldOutState : public State { 9 public: 10 SoldOutState( GumballMachine &_gumball_machine ) : State(_gumball_machine) {} 11 void insert_quarter() { 12 std::cout << "You can't insert a quarter, the machine is sold out" << std::endl; 13 } 14 void eject_quarter() { 15 std::cout << "you can't eject, you haven't inserted a quarter yet" << std::endl; 16 } 17 void turn_crank() { 18 std::cout << "You turned, but there's no gumballs" << std::endl; 19 } 20 void dispense() { 21 std::cout << "No gumball dispensed" << std::endl; 22 } 23 }; 24 25 class NoQuarterState : public State { 26 public: 27 NoQuarterState( GumballMachine &_gumball_machine ): State(_gumball_machine) {} 28 void insert_quarter() { 29 std::cout << "You inserted a quarter" << std::endl; 30 gumball_machine.set_state( gumball_machine.get_has_quarter_state() ); 31 } 32 void eject_quarter() { 33 std::cout << "You haven't inserted a quarter" << std::endl; 34 } 35 void turn_crank() { 36 std::cout << "You turned, but there's no quarter" << std::endl; 37 } 38 void dispense() { 39 std::cout << "You need to pay first" << std::endl; 40 } 41 }; 42 43 class HasQuarterState : public State { 44 public: 45 HasQuarterState( GumballMachine & _gumball_machine ) : State(_gumball_machine) {} 46 void insert_quarter() { 47 std::cout << "You can't insert another quarter" << std::endl; 48 } 49 void eject_quarter() { 50 std::cout << "Quarter returned" << std::endl; 51 gumball_machine.set_state( gumball_machine.get_no_quarter_state() ); 52 } 53 void turn_crank() { 54 std::cout << "You turned..." << std::endl; 55 gumball_machine.set_state( gumball_machine.get_sold_state() ); 56 } 57 void dispense() { 58 std::cout << "No gumball dispensed" << std::endl; 59 } 60 }; 61 class SoldState : public State { 62 public: 63 SoldState( GumballMachine &_gumball_machine ) : State(_gumball_machine) {} 64 void insert_quarter() { 65 std::cout << "Please wait, we're already giving you a gumball" << std::endl; 66 } 67 void eject_quarter() { 68 std::cout << "Sorry, you already turned the crank" << std::endl; 69 } 70 void turn_crank() { 71 std::cout << "Turning twice doesn't get you another gumball!" << std::endl; 72 } 73 void dispense() { 74 gumball_machine.release_ball(); 75 if ( 0 == gumball_machine.get_count() ) { 76 gumball_machine.set_state( gumball_machine.get_sold_out_state() ); 77 } 78 else { 79 gumball_machine.set_state( gumball_machine.get_no_quarter_state() ); 80 } 81 } 82 }; 83 84 SoldOutState sold_out_state; 85 NoQuarterState no_quarter_state; 86 HasQuarterState has_quarter_state; 87 SoldState sold_state; 88 State *state; 89 unsigned count; 90 public: 91 GumballMachine( unsigned _count ) : 92 count(_count), 93 sold_out_state( *this ), 94 no_quarter_state( *this ), 95 has_quarter_state( *this ), 96 sold_state( *this ) { 97 if ( 0 == count ) { 98 state = &sold_out_state; 99 } 100 else { 101 state = &no_quarter_state; 102 } 103 } 104 void release_ball() { 105 std::cout << "A gumball comes rolling out the slot" << std::endl; 106 count--; 107 if ( 0 == count ) { 108 std::cout << "Oops, out of gumballs!" << std::endl; 109 } 110 } 111 unsigned get_count() { return count; } 112 void insert_quarter() { state->insert_quarter(); } 113 void eject_quarter() { state->eject_quarter(); } 114 void turn_crank() { state->turn_crank(); state->dispense(); } 115 void set_state( State *_state ) { state = _state; } 116 State *get_sold_out_state() { return &sold_out_state; } 117 State *get_no_quarter_state() { return &no_quarter_state; } 118 State *get_has_quarter_state() { return &has_quarter_state; } 119 State *get_sold_state() { return &sold_state; } 120 }; 121 #endif
main.cpp
1 #include "gumball_machine.h" 2 3 int main() { 4 GumballMachine gumball_machine(2); 5 6 gumball_machine.insert_quarter(); 7 gumball_machine.eject_quarter(); 8 gumball_machine.insert_quarter(); 9 gumball_machine.turn_crank(); 10 11 gumball_machine.insert_quarter(); 12 gumball_machine.eject_quarter(); 13 gumball_machine.insert_quarter(); 14 gumball_machine.turn_crank(); 15 16 17 gumball_machine.insert_quarter(); 18 gumball_machine.eject_quarter(); 19 gumball_machine.insert_quarter(); 20 gumball_machine.turn_crank(); 21 return 0; 22 }