1、状态模式定义
状态对象:在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
状态模式(State Pattern) :类的行为是基于它的状态改变的。状态模式的别名为状态对象(Objects for States)。
2、状态模式结构
状态模式包含如下角色:
- Context: 环境类
- State: 抽象状态类
- ConcreteState: 具体状态类
3、状态模式的实现
这里我们以程序员上班工作为例,状态分为 上午,中午,下午和晚上。
#ifndef STATE_H_ #define STATE_H_ #include <cstdio> // class State; class Work { private: State* state_; int hour_; public: Work(); ~Work(); void SetHour(int hour); int GetHour(); void SetState(State* state); State* GetState(); void WriteProgram(); }; class State { public: virtual void WriteProgram(Work* work) {}; virtual ~State(){} }; class ForenoonState : public State { public: void WriteProgram(Work* work); }; class NoonState : public State { public: void WriteProgram(Work* work); }; class AfternoonState : public State { public: void WriteProgram(Work* work); }; class EveningState : public State { public: void WriteProgram(Work* work); }; class SleepingState : public State { public: void WriteProgram(Work* work); }; class RestState :public State { public: void WriteProgram(Work* work) { printf("Rest state\n"); } }; #endif
#include "state.h" Work::Work() { state_ = new ForenoonState(); } Work::~Work() { if (state_ != NULL) { delete state_; } } void Work::SetHour(int hour) { hour_ = hour; } int Work::GetHour() { return hour_; } void Work::SetState(State* state) { state_ = state; } State* Work::GetState() { return state_; } void Work::WriteProgram() { state_->WriteProgram(this); } void ForenoonState::WriteProgram(Work* work) { if (work->GetHour() < 12) { printf("forenoon work state\n"); } else { State* sta = work->GetState(); delete sta; work->SetState(new NoonState()); work->WriteProgram(); } } void NoonState::WriteProgram(Work* work) { if (work->GetHour() < 13) { printf("noon work state\n"); } else { State* sta = work->GetState(); delete sta; work->SetState(new AfternoonState()); work->WriteProgram(); } } void AfternoonState::WriteProgram(Work* work) { if (work->GetHour() < 17) { printf("AfternoonState work state\n"); } else { State* sta = work->GetState(); delete sta; work->SetState(new EveningState()); work->WriteProgram(); } } void EveningState::WriteProgram(Work* work) { if (work->GetHour() < 21) { printf("EveningState work state\n"); } else { State* sta = work->GetState(); delete sta; work->SetState(new SleepingState); work->WriteProgram(); } } void SleepingState::WriteProgram(Work* work) { if (work->GetHour() < 22) { printf("Sleeping state\n"); } else { State* sta = work->GetState(); delete sta; work->SetState(new RestState()); work->WriteProgram(); } }
4、状态模式的优缺点
1、枚举可能的状态,在枚举状态之前需要确定状态种类
2、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、状态模式的使用环境
状态模式可以适用于条件状态多但可以通过穷举法列出所有情况的开发模式中,典型的应用就是TCP三次握手的状态转换、游戏中状态装换和办公系统的处理状态等等。