状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
本文使用书中工作状态的例子,代码使用C++语言描述,代码存在的不足或问题有望各位指出。
(1)状态模式框架
#include <iostream>
using namespace std;
class Context;
class State
{
public:
State(){}
virtual ~State(){}
virtual void handle(Context *context)=0;
};
class ConcreteStateB;
class ConcreteStateA: public State
{
public:
void handle(Context *context) override;
};
class ConcreteStateB: public State
{
public:
void handle(Context *context) override;
};
class Context
{
// friend State;
public:
Context(State *state)
{
this->state =state;
}
~Context()
{
delete state;
}
State* get()
{
return state;
}
void set( State *state)
{
this->state = state;
cout << "当前状态:" <<endl;
}
void Request()
{
state->handle(this);
}
private:
State *state;
};
void ConcreteStateA::handle(Context *context)
{
context->set(new ConcreteStateB());
cout << "ConcreteStateA"<<endl;
}
void ConcreteStateB::handle(Context *context)
{
context->set(new ConcreteStateA());
cout<< "ConcreteStateB" <<endl;
}
int main()
{
Context *c =new Context(new ConcreteStateA());
c->Request();
c->Request();
c->Request();
c->Request();
delete c;
return 0;
}
(2) 工作状态实现状态模式
#include <iostream>
using namespace std;
class Work;
class State
{
public:
State(){}
virtual ~State(){}
virtual void writeProgram(Work *w)=0;
};
//上午工作状态
class ForenoonState: public State
{
public:
void writeProgram(Work *w) override;
};
//下午工作状态
class NoonState:public State
{
public:
void writeProgram(Work *w) override;
};
//傍晚工作状态
class AfternoonState: public State
{
public:
void writeProgram(Work *w) override;
};
//晚间工作状态
class EveningState:public State
{
public:
void writeProgram(Work *w) override;
};
//睡眠状态
class SleepingState:public State
{
public:
void writeProgram(Work *w) override;
};
//下班休息状态
class RestState: public State
{
public:
void writeProgram(Work *w) override;
};
class Work
{
public:
Work()
{
current = new ForenoonState();
}
~Work()
{
delete current;
}
double getHour()
{
return hour;
}
void setHour(double value)
{
hour = value;
}
bool taskFinished()
{
return finish;
}
void setTaskFinished(bool value)
{
finish = value;
}
void setState(State *s)
{
current =s;
}
void writeProgram()
{
current->writeProgram(this);
}
private:
State *current;
double hour;
bool finish=false;
};
void ForenoonState::writeProgram(Work *w)
{
if(w->getHour() < 12)
cout << "当前时间:"<<w->getHour()<<"点 上午工作,精神百倍"<<endl;
else
{
w->setState(new NoonState());
w->writeProgram();
}
}
void NoonState::writeProgram(Work *w)
{
if(w->getHour()<13)
{
cout << "当前时间:"<<w->getHour()<<"点 饿了,午饭;犯困,午休。"<<endl;
}
else
{
w->setState(new AfternoonState());
w->writeProgram();
}
};
void AfternoonState::writeProgram(Work *w)
{
if(w->getHour()<17)
{
cout << "当前时间:"<<w->getHour()<<"点 下午状态还不错,继续努力。"<<endl;
}
else
{
w->setState(new EveningState());
w->writeProgram();
}
}
void EveningState::writeProgram(Work *w)
{
if(w->taskFinished())
{
w->setState(new RestState());
w->writeProgram();
}
else
{
if(w->getHour()<21)
{
cout << "当前时间:"<<w->getHour()<<"点 加班呦,疲累之极。"<<endl;
}
else
{
w->setState(new EveningState());
w->writeProgram();
}
}
}
void SleepingState::writeProgram(Work *w)
{
cout << "当前时间:"<<w->getHour()<<"点 不行了,睡着了。"<<endl;
}
void RestState::writeProgram(Work *w)
{
cout << "当前时间:"<<w->getHour()<<"点 下班回家了。"<<endl;
}
int main()
{
Work *emergencyProjects = new Work();
emergencyProjects->setHour(9);
emergencyProjects->writeProgram();
emergencyProjects->setHour(10);
emergencyProjects->writeProgram();
emergencyProjects->setHour(12);
emergencyProjects->writeProgram();
emergencyProjects->setHour(13);
emergencyProjects->writeProgram();
emergencyProjects->setHour(14);
emergencyProjects->writeProgram();
emergencyProjects->setHour(17);
emergencyProjects->writeProgram();
emergencyProjects->setTaskFinished(false);
emergencyProjects->setHour(19);
emergencyProjects->writeProgram();
emergencyProjects->setHour(22);
emergencyProjects->writeProgram();
delete emergencyProjects;
return 0;
}
状态模式好处与用处
1、状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分隔开来。就是将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类很容易地增加新的状态和转换。
2、目的为了消除庞大的条件分支语句,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
3、当一个对象的行为取决于它的状态,并且他必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。