状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
状态模式的优点:将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
抽象状态类:定义一个接口封装 与context的一个状态相关的 行为
这个状态是Context中的私有属性
状态模式就是通过把各种状态的逻辑转移到state的各个子类中,减少相互依赖。
这样做可以消除庞大的条件分支语句
以COC中的兵营为例
当建造的时候只有土地和护栏;当升级的时候会影响造兵速度;当兵满的时候会显示兵营已满;当正在训练的时候会有训练兵的特效。
state.h
#ifndef DESIGN_PATTERN_STATE_H
#define DESIGN_PATTERN_STATE_H
#include<iostream>
#include"Barrack.h"
using std::cout;
using std::endl;
class Barrack;
class barrack_state{
public:
virtual void show(Barrack* barrack);
};
class barrack_building : public barrack_state {//公有继承
public:
void show(Barrack* barrack) override ;
};
class barrack_upgrading :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
class barrack_full :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
class barrack_training :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
#endif //DESIGN_PATTERN_STATE_H
state.cpp
#include "State.h"
void barrack_building::show(Barrack* barrack)
{
if(barrack->statetype=="building")
cout << "building and fence" << endl;
}
void barrack_upgrading::show(Barrack* barrack)
{
if(barrack->statetype=="upgrading")
cout << "upgrading" << endl;
}
void barrack_state::show(Barrack* barrack)
{
}
void barrack_full::show(Barrack* barrack)
{
if (barrack->statetype=="full")
{
cout << "full" << endl;
}
}
void barrack_training::show(Barrack* barrack)
{
if(barrack->statetype=="training")
cout << "trainging" << endl;
}
Barrack.h
#ifndef DESIGN_PATTERN_BARRACK_H
#define DESIGN_PATTERN_BARRACK_H
#include<string>
#include"State.h"
using std::string;
class barrack_state;
class Barrack{
public:
Barrack();
void show();
void upgrading();
void trainging();
void full();
string statetype;
private:
barrack_state* state;
};
#endif //DESIGN_PATTERN_BARRACK_H
Barrack.cpp
#include "Barrack.h"
Barrack::Barrack()
{
statetype = "building";
this->state = new barrack_building();//只有公有继承才能转换为基类
}
void Barrack::show()
{
this->state->show(this);
}
void Barrack::upgrading()
{
statetype = "upgrading";
state = new barrack_upgrading();
}
void Barrack::trainging()
{
statetype = "training";
state = new barrack_training();
}
void Barrack::full()
{
statetype = "full";
state = new barrack_full();
}
头文件互相包含问题
在自己写状态模式的过程中,发现出现类名未声明的情况,百思不得其解,不断调试未果。灵光乍现,怀疑是头文件互相包含导致的问题,遂查资料找到问题并解决。
不可避免的存在头文件互相包含的情况。
涉及到C/C++编译原理,与参考资料中的情况略微不同,其func中会使用Class A,而在Class A中没有func,从而只需要在func之前加上Class A的声明即可正确运行。
而状态模式的使用中,Context类的声明中会有State类,State类的声明中会有Context类,所以需要在分别在各自前方声明另一个类。如上述代码所示。