2007年2月15日

针对switch/case的小重构

这是放假前的任务了,总觉得代码里有种怪气味,回家的路上看了《设计模式解析》。

需求是这样的:要模仿昆虫的飞行
把昆虫看作一个状态机的话,它的状态包括:位置(pos),俯仰角(pitchAngle),偏航角(yawAngle),翅膀角度(wingAngle)。
位置是昆虫在世界坐标系(三维空间)里的坐标,有x,y,z三个分量。俯仰角表示昆虫身体与水平面的夹角。偏航角表示与竖直平面的夹角。这样的抽象可能有点过于简单,不过现在假定可以满足需求。
最初的想法是采集蝴蝶的飞行过程中的数据,然后用这些数据设置昆虫的状态来模拟昆虫的飞行,这样的话变成难度比较小并且效果应该很好。这样就有两个模块RouteBuilder负责载入数据,MoveInsect负责设置数据改变状态。


void MoveInsect::Move()
{
GetData();
SetInsectState();
}

因为采集数据太困难我们使用了自己生成的数据,这样的生成数据以节点(Node)的形式给出来。Node里包含的并不是要设置的量,而是改变量。比如现在的速度是1,节点里的改变量是2,应用这个节点后速度的值就是3。生成数据的时候发现要寻找昆虫的飞行规律,比如有攀升,俯冲等姿势。这样麻烦就产生了,比如攀升这个动作是需要知道当前状态的,因为攀升时振翅的速度会加快,但是可能上一个状态也是攀升,振翅的速度就已经加快了。这样就必须让MoveInsect知道Node所处的状态。现在的代码

struct Node
{
......
NodeType type_;
}

void MoveInsect::Move()
{
GetData();
SetInsectState();
OtherNodeOp(curNode_);
}
void MoveInsect::OtherNodeOp(Node& node)
{
switch(node.type_)
{
case SWOOP:
break;
......
}
}
设计模式解析里说,switch通常意味着重构的必要
我对模式了解并不多,但是我有一个办法。做一个类的继承体系,基类是NodeMove,派生类包括Swoop等,为MoveInsect增加一个NodeMove& nodeMove_;成员。
但是这样做的作用是什么呢,有多少好处呢,貌似并不多。首先当然是没有了switch,然后呢对象的职责更加明确,并且修改被限制在一个更小的范围内(一个类中)。还有额外的成本,为了修改昆虫的状态我必须声明友元。我得想点别的办法了,借助设计模式的力量,待续

没有评论: