state模式:水蒸汽和冰都是水在不同温度下的状态。将 水,冰,水蒸汽,每种形态看做一种类型。将常温,加热到100度,零下10度,看成是三个动作。
对于水,冰,水蒸汽这三个类来说,对于三个动作都有分别的反应,并且在特定条件下,会变身成其他的类型。例如 水 在 加热到100度 的时候会变身成 水蒸汽。
对于一瓶水来说,我们只需要记录“当前的状态”,然后调用 三个动作的序列,通过 “当前的状态”在不同动作下自身的变化,就能得到最终 这瓶水 的 形态了。
#include <stdio.h>
#define SOLD_OUT (0)
#define NO_QUARTER (1)
#define HAS_QUARTER (0)
#define SOLD (3)
class GamballMachine
{
int state;
int count;
public :GamballMachine(int count)
{
this->count = count;
if (count > 0)
{
state = NO_QUARTER;
}
}
void insert_quarter()
{
if (state == HAS_QUARTER)
{
printf("you can't insert another quarter.\n");
}
else if (state == NO_QUARTER)
{
state = HAS_QUARTER;
printf("you inserted a quarter.\n");
}
else if (state == SOLD_OUT)
{
printf("you can't insert a quarter, the machine is sold out.\n");
}
else if (state == SOLD)
{
printf("please wait, we're already giving you a gamball.\n");
}
}
void eject_quarter()
{
if (state == HAS_QUARTER)
{
printf("quarter returned.\n");
state = NO_QUARTER;
}
else if (state == NO_QUARTER)
{
printf("you haven't inserted a quarter.\n");
}
else if (state == SOLD_OUT)
{
printf("you can't eject, you haven't inserted a quarter yet.\n");
}
else if (state == SOLD)
{
printf("sorry. you already turned the crank.\n");
}
}
void turn_crank()
{
if (state == HAS_QUARTER)
{
printf("you turned.\n");
state = SOLD;
dispense();
}
else if (state == NO_QUARTER)
{
printf("you turned, but there is no quarter.\n");
}
else if (state == SOLD_OUT)
{
printf("you turned, but there is no gamballs.\n");
}
else if (state == SOLD)
{
printf("the gamball is solding, turned again doesn't take effect.\n");
}
}
void dispense()
{
if (state == HAS_QUARTER)
{
printf("no gamball dispensed.\n");
}
else if (state == NO_QUARTER)
{
printf("you need to pay first.\n");
}
else if (state == SOLD_OUT)
{
printf("no gamball dispensed.\n");
}
else if (state == SOLD)
{
printf("a gamball comes rolling out of the slot.\n");
count = count - 1;
if (count == 0)
{
state = SOLD_OUT;
}
else
{
state = NO_QUARTER;
}
}
}
};
int gamball_machine_test()
{
printf("\n\n===========gamball_machine test=======\n\n");
GamballMachine gamball_machine = GamballMachine(5);
gamball_machine.insert_quarter();
gamball_machine.turn_crank();
printf("\n\n");
gamball_machine.insert_quarter();
gamball_machine.eject_quarter();
gamball_machine.turn_crank();
return 1;
}
//use state pattern to rewrite
class State
{
public :
virtual int insert_quarter() = 0;
virtual int eject_quarter() = 0;
virtual int turn_crank() = 0;
virtual int dispense() = 0;
};
class HasQuarter_State;
class NoQuarter_State;
class Soldout_State;
class Sold_State;
class GamballMachine_New
{
public:
State *has_quarter_state;
State *no_quarter_state;
State *soldout_state;
State *sold_state;
State *state;
int count;
public:
GamballMachine_New(int count);
public:
int set_state(State *state);
HasQuarter_State *get_has_quarter_state();
NoQuarter_State *get_no_quarter_state();
Soldout_State *get_soldout_state();
Sold_State *get_sold_state();
int insert_quarter();
int eject_quarter();
int turn_crank();
int dispense();
};
class HasQuarter_State:public State
{
public:
GamballMachine_New *gamball_machine;
public: HasQuarter_State(GamballMachine_New *gamball_machine)
{
this->gamball_machine = gamball_machine;
}
int insert_quarter()
{
printf("you can't insert another quarter.\n");
return 0;
}
int eject_quarter()
{
printf("quarter returned.\n");
gamball_machine->set_state((State *)gamball_machine->get_no_quarter_state());
return 0;
}
int turn_crank()
{
printf("you turned.\n");
gamball_machine->set_state((State *)gamball_machine->get_sold_state());
gamball_machine->dispense();
return 0;
}
int dispense()
{
printf("no gamball dispensed.\n");
return 0;
}
};
class NoQuarter_State:public State
{
public:
GamballMachine_New *gamball_machine;
public:
NoQuarter_State(GamballMachine_New *gamball_machine)
{
this->gamball_machine = gamball_machine;
}
int insert_quarter()
{
gamball_machine->set_state(gamball_machine->get_has_quarter_state());
printf("you inserted a quarter.\n");
return 0;
}
int eject_quarter()
{
printf("you haven't inserted a quarter.\n");
return 0;
}
int turn_crank()
{
printf("you turned, but there is no quarter.\n");
return 0;
}
int dispense()
{
printf("you need to pay first.\n");
return 0;
}
};
class Soldout_State:public State
{
GamballMachine_New *gamball_machine;
public:
Soldout_State(GamballMachine_New *gamball_machine)
{
this->gamball_machine = gamball_machine;
}
int insert_quarter()
{
printf("you can't insert a quarter, the machine is sold out.\n");
return 0;
}
int eject_quarter()
{
printf("you can't eject, you haven't inserted a quarter yet.\n");
return 0;
}
int turn_crank()
{
printf("you turned, but there is no gamballs.\n");
return 0;
}
int dispense()
{
printf("no gamball dispensed.\n");
return 0;
}
};
class Sold_State:public State
{
GamballMachine_New *gamball_machine;
public:
Sold_State(GamballMachine_New *gamball_machine)
{
this->gamball_machine = gamball_machine;
}
int insert_quarter()
{
printf("please wait, we're already giving you a gamball.\n");
return 0;
}
int eject_quarter()
{
printf("sorry. you already turned the crank.\n");
return 0;
}
int turn_crank()
{
printf("the gamball is solding, turned again doesn't take effect.\n");
return 0;
}
int dispense()
{
printf("a gamball comes rolling out of the slot.\n");
gamball_machine->count = gamball_machine->count - 1;
if (gamball_machine->count == 0)
{
gamball_machine->set_state(gamball_machine->get_soldout_state());
}
else
{
gamball_machine->set_state(gamball_machine->get_no_quarter_state());
}
return 0;
}
};
GamballMachine_New::GamballMachine_New(int count)
{
this->state = (new NoQuarter_State(this));
this->has_quarter_state = (new HasQuarter_State(this)) ;
this->no_quarter_state = (new NoQuarter_State(this));
this->soldout_state = (new Soldout_State(this));
this->sold_state = (new Sold_State(this));
this->count = count;
}
int GamballMachine_New::set_state(State *state)
{
this->state = state;
return 0;
}
HasQuarter_State* GamballMachine_New::get_has_quarter_state()
{
return (HasQuarter_State*)has_quarter_state;
}
NoQuarter_State* GamballMachine_New::get_no_quarter_state()
{
return (NoQuarter_State*)no_quarter_state;
}
Soldout_State* GamballMachine_New::get_soldout_state()
{
return (Soldout_State*)soldout_state;
}
Sold_State* GamballMachine_New::get_sold_state()
{
return (Sold_State*)sold_state;
}
int GamballMachine_New::insert_quarter()
{
this->state->insert_quarter();
return 0;
}
int GamballMachine_New::eject_quarter()
{
this->state->eject_quarter();
return 0;
}
int GamballMachine_New::turn_crank()
{
this->state->turn_crank();
return 0;
}
int GamballMachine_New::dispense()
{
this->state->dispense();
return 0;
}
int gamball_machine_new_test()
{
printf("\n\n===========gamball_machine use state pattern test=======\n\n");
GamballMachine_New gamball_machine = GamballMachine_New(5);
gamball_machine.insert_quarter();
gamball_machine.turn_crank();
printf("\n\n");
gamball_machine.insert_quarter();
gamball_machine.eject_quarter();
gamball_machine.turn_crank();
return 1;
}
int main()
{
gamball_machine_test();
gamball_machine_new_test();
getchar();
}