允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象。
状态模式一般包含Context(环境类)、State(抽象状态类)和ConcreteState(具体状态类)。
从类图可知,ForumnAccount(论坛账户类)互相关联AbstractState(抽象状态类), 账户类的downloadFile、writeNote和replyNote等操作都由状态类的相关函数来操作,方便进行状态之前的转换。
下面是c++实现的版本。
由于c++对互相关联的类和调用并不友好,需要一定的声明和定义技巧,所以下面的代码顺序有点乱。
(也可以将代码分为h头文件和cpp文件,这样就不会出现这些问题,因为我是为了方便写在同一个cpp中)
环境类ForumAccount(论坛账号类)
//环境类ForumAccount(论坛账号类)
class AbstractState;
class ForumAccount{
public:
ForumAccount(string name);
void setState(AbstractState *state){
this->state = state;
}
AbstractState* getState(){
return this->state;
}
string getName(){
return this->name;
}
//定义在后面
void downloadFile(int score);
void writeNote(int score);
void replyNote(int score);
private:
AbstractState *state;
string name;
};
抽象类AbstractState(账号状态类)
//抽象类AbstractState(账号状态类)
class AbstractState{
public:
virtual void checkState(int score) = 0;
virtual void downloadFile(int score){
cout << acc->getName() << "下载文件,扣除" << score << "积分。" << endl;
this->point -= score;
checkState(score);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
virtual void writeNote(int score){
cout << acc->getName() << "发布留言,增加" << score << "积分。" << endl;
this->point += score;
checkState(score);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
virtual void replyNote(int score){
cout << acc->getName() << "回复留言,增加" << score << "积分。" << endl;
this->point += score;
checkState(score);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
void setPoint(int point){
this->point = point;
}
int getPoint(){
return this->point;
}
void setStateName(string stateName){
this->stateName = stateName;
}
ForumAccount* getAcc(){
return acc;
}
string getStateName(){
return stateName;
}
protected:
ForumAccount *acc;
int point;
string stateName;
};
具体状态类PrimaryState(新手状态类)
//具体状态类PrimaryState(新手状态类)
class PrimaryState : public AbstractState{
public:
PrimaryState(AbstractState *state){
this->acc = state->getAcc();
this->point = state->getPoint();
this->stateName = "新手";
}
PrimaryState(ForumAccount *acc){
this->acc = acc;
this->point = 0;
this->stateName = "新手";
}
void downloadFile(int score){
cout << "对不起," << acc->getName() << ",您没有下载文件的权限!" << endl;
}
void checkState(int socre);
};
具体状态类MiddleState(高手状态类)
//具体状态类MiddleState(高手状态类)
class MiddleState : public AbstractState{
public:
MiddleState(AbstractState *state){
this->acc = state->getAcc();
this->point = state->getPoint();
this->stateName = "高手";
}
void writeNote(int score){
cout << acc->getName() << "发布留言,增加" << score << "*2个积分。" << endl;
this->point += score*2;
checkState(score);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
void checkState(int socre);
};
具体状态类HighState(专家状态类)
//具体状态类HighState(专家状态类)
class HighState : public AbstractState{
public:
HighState(AbstractState *state){
this->acc = state->getAcc();
this->point = state->getPoint();
this->stateName = "专家";
}
void writeNote(int score){
cout << acc->getName() << "发布留言,增加" << score << "*2个积分。" << endl;
this->point += score*2;
checkState(score);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
void downloadFile(int score){
cout << acc->getName() << "下载文件,扣除" << score << "/2个积分。" << endl;
this->point -= score/2;
checkState(score/2);
cout << "剩余积分为:" << this->point << ",当前级别为:" << acc->getState()->getStateName() << "。" << endl;
}
void checkState(int score);
};
后置定义代码
//这里的定义需要放在这里,不然编译不通过,可以将声明和定义分开成.h和.cpp
ForumAccount::ForumAccount(string name){
this->name = name;
this->state = new PrimaryState(this);
cout << this->name << "注册成功!" << endl;
}
void ForumAccount::downloadFile(int score){
state->downloadFile(score);
}
void ForumAccount::writeNote(int score){
state->writeNote(score);
}
void ForumAccount::replyNote(int score){
state->replyNote(score);
}
//这里存在内存泄漏,可改为智能指针
void PrimaryState::checkState(int score){
if(point>=1000){
acc->setState(new HighState(this));
}else if(point>=100){
acc->setState(new MiddleState(this));
}
}
void MiddleState::checkState(int score){
if(point>=1000){
acc->setState(new HighState(this));
}else if(point<0){
cout << "余额不足,操作失败!" << endl;
this->point += score;
}else if(point<=100){
acc->setState(new PrimaryState(this));
}
}
void HighState::checkState(int score){
if(point<0){
cout << "余额不足,操作失败!" << endl;
this->point += score;
}else if(point<=1000){
acc->setState(new MiddleState(this));
}else if(point<=100){
acc->setState(new PrimaryState(this));
}
}
客户端测试
//客户端测试
int main(void){
//注册用户
ForumAccount account("张三");
//操作
account.writeNote(20);
account.downloadFile(20);
account.replyNote(100);
account.writeNote(40);
account.downloadFile(80);
account.downloadFile(150);
account.writeNote(1000);
account.downloadFile(80);
return 0;
}
输出结果