1. 概述
State Pattern即状态模式。一个简单的case:
对于自动门来说,有两种状态:open和close,如果门处于open状态,如果用户再按open按钮,没有反应,如果按下close键,则门关闭。
switch...case...实现:
const int OPEN = 1; // door open 状态
const int CLOSE = 2;// door close 状态
class Manage
{
public:
void open()
{
switch(door.state)
{
case OPEN :
do nothing;
break;
case CLOSE:
open the door;
break;
default:
break;
}
}
}
可以看到,状态及相应的操作都由Manage类来管理,状态和相应操作没有隔离,无法独立变化;此外,如果状态过多,会带来Manage类代码过于复杂的问题。
为此,引入State Pattern,主要应用于:
1)一个对象的行为取决于它的状态的场景。
2)有限状态自动机
state的类图:
Manage:对client提供服务接口
State:状态抽象基类
State_x:具体状态类,定义该状态下相应操作的具体行为
有一个非常重要的点,状态迁移由谁来控制,两种方案:
1)由Manage类来负责状态迁移
2)State类本身负责状态迁移
前者的缺点在于增加新的状态类较复杂,如果状态过多,状态迁移负责,会带来Manage类过于复杂,此外,Manage类需要了解具体的状态类
后者的缺点在于各个state对象必须知晓其兄弟state对象的存在,为此带来了state子类之间的依赖。
2. 例子
餐馆Waiter有两种状态:busyness和idle,如果Waiter正在忙碌,则无法响应客人的服务请求,如果正处于Idle状态,则可以响应客人的请求,并把自己的状态置为Busyness
State Pattern实现方法(state子类负责状态迁移)
#include <iostream>
using namespace std;
class Waiter
{
public:
Waiter();
void request();
void setCur(class State* state)
{
_cur = state;
}
private:
State *_cur;
};
class State
{
public:
virtual ~State()
{
}
virtual void request(Waiter*) = 0;
};
class Busyness_state : public State
{
public:
void request(Waiter*)
{
cout << "Waiter: i am busy, boss" << endl;
}
};
class Idle_state : public State
{
public:
void request(Waiter* waiter)
{
cout << "Waiter: i am coming" << endl;
waiter->setCur(new Busyness_state);
cout << "Waiter state change from idle to business" << endl;
delete this;
}
};
Waiter::Waiter()
{
_cur = new Idle_state();
}
void Waiter::request()
{
cout << "Client: service request" << endl;
_cur->request(this);
}
int main()
{
Waiter waiter;
waiter.request();
waiter.request();
waiter.request();
return 0;
}
输出:
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Client: service request
Waiter: i am busy, boss
State Pattern实现2(Manage负责状态迁移)
#include <iostream>
#include <vector>
using namespace std;
class Waiter
{
public:
Waiter();
void request();
void setCur(class State* state)
{
if(_cur)
{
delete _cur;
}
_cur = state;
}
private:
State *_cur;
};
class State
{
public:
virtual ~State()
{
}
virtual bool request() = 0;
};
class Busyness_state : public State
{
public:
bool request()
{
cout << "Waiter: i am busy, boss" << endl;
return false;
}
};
class Idle_state : public State
{
public:
bool request()
{
cout << "Waiter: i am coming" << endl;
return true;
}
};
Waiter::Waiter()
{
_cur = new Idle_state();
}
void Waiter::request()
{
cout << "Client: service request" << endl;
if(_cur->request())
{
setCur(new Busyness_state);
cout << "Waiter state change from idle to business" << endl;
}
else
{
cout << "Waiting....." << endl;
}
}
int main()
{
Waiter waiter;
waiter.request();
waiter.request();
waiter.request();
return 0;
}
输出:
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Waiting.....
Client: service request
Waiter: i am busy, boss
Waiting.....