学以致用C++设计模式 之 “状态模式”

学以致用C++设计模式 之 “状态模式”_第1张图片

文章目录

    • 从DFA讲起
    • 游戏角色
    • 什么是状态模式
      • 状态模式的应用
        • 优点:
        • 缺点:

从DFA讲起

何为DFA?确定的有穷状态机。这里

看完上面那篇博客,就明白状态机还挺好用的。
那么现在,转场。

游戏角色

要开发一款游戏,咱负责的模块是处理游戏角色属性框架的搭建,目前已知角色有:坦克、法师、射手,他们都有属性:血量、物攻、物抗、法攻、法抗、角色转换技能。

同样,可以采用自动机的方式来进行处理:

坦克 法师 射手
坦克 - 双抗-,法攻+ 双抗-,物攻+
法师 双抗+,法攻- - 物攻+,法攻-
射手 双抗+,物攻- 物攻-,法攻+ -

也挺好办的,就这样封装好了。

但是,这毕竟是C语言的方式,面向过程,如果我要拓展,加俩新角色进去呢?加个近战战士,怎么办?把写好的代码拆了重写?那明天再加个辅助进去,再重写?

既然学了面向对象,那就用面向对象的方式来解决这类问题:将每种状态封装成类,然后该怎么办就不用我多说了。

类怎么设计呢?看这样好不好:

class 坦克{
private:
	int 血量;
	int 物攻;
	int	物抗;
	int 法攻;
	int 法抗;
public:
	void 攻击();
	void 防守();
	void 技能();
}

可还行?
然后场景类就这样:

int main(){

	class* 坦克兵 = new 坦克();
	class* 魔法师 = new 法师();
	class* 狙击手 = new 射手();
	
//被人打了,用坦克
	坦克兵->防守();

//要打消耗,用法师
	魔法师->攻击();

//敌人要跑,用射手
	狙击手->技能();

···
}

这样始终是零散,疏于管教。而且,并不能实现自动啊,顶多就是个手动状态机。
那怎么弄哦?将前边的DFA再看看,再配上责任链的思想,想想就知道该来了父类,然后每个子类中自己管理自己的状态,再维护一条状态链表,实现有穷的自动状态机(C++状态模式版)。

你看这样可好?

class 状态基类{
private:
	string 当前状态;
	状态基类* 下一状态;
public:
	virtual void 攻击();
	virtual void 防守();
	virtual void 技能();
	void setState(string 状态){this->当前状态 = 状态;}
	void setNextNode(状态基类* 下一状态){this->下一状态 = 下一状态;};
	状态基类* 遍历状态(string 目标状态){
		if(this->当前状态 == 目标状态)
			return this;
		else if(this->下一状态 != NULL)
			下一状态->遍历状态(目标状态);
		else
			return NULL;
	}
}

class 坦克:public 状态基类{
public:
	void 攻击(){···}
	void 防守(){···}
	void 技能(){···}
}

···

场景类就这样实现了:

状态基类* 状态1 = new 坦克();
状态基类* 状态2 = new 战士();
状态基类* 状态3 = new 法师();
状态基类* 状态4 = new 射手();

状态基类* 当前状态;

状态1->setState("坦克");
状态2->setState("战士");
状态3->setState("法师");
状态4->setState("射手");


状态1->setNextNode(状态2);
状态2->setNextNode(状态3);
状态3->setNextNode(状态4);

//被人打了
当前状态 = 状态1->遍历状态(坦克);
当前状态->防守();

//要打消耗,用法师
当前状态 = 状态1->遍历状态(法师);
当前状态->攻击();

//敌人要跑,用射手
当前状态 = 状态1->遍历状态(射手);
当前状态->技能();

//中埋伏了,换战士
当前状态 = 状态1->遍历状态(战士);
当前状态->攻击();
当前状态->防守();
当前状态->放技能();

这样连轴转。


什么是状态模式

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其种类。

状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样。

状态模式的应用

优点:

结构清晰、遵循设计原则、封装性好

缺点:

要避免状态过多。

学以致用C++设计模式 之 “状态模式”_第2张图片

你可能感兴趣的:(#,设计模式进阶)