威老迷宫探险第二季--如何更面向对象
话说在第一季中,威老探访了乾陵,并成功地取回了大量的宝藏。
想看第一季的朋友请进
这次,威老卷土重来,前往***。。等待他的将是什么样的危险呢?
去***的人,都再也没有回来过,相传在那里生活着一群吃人的Monster,它们每天都在四处游荡。任何访客一旦碰上Monster,就会立马被吃掉!
OK,这就是我们这次的迷宫。
经过分析,我们可以发现,Monster和Explorer是有许多的共性的。他们都能够做简单判断,看四周的情况,并且都能够移动。这些所以这些函数我们可以提取出来,做成类供Monster和Explorer调用,以提高代码的可重用性。
我首先想到创建一个名为"RouteChecker"的类,然后把IsEastWalkAble()、IsSouthWalkAble()、IsWestWalkAble()、IsNorthWalkAble()、IsWalkAble()这几个函数通通装到 "RouteChecker" 里。这样一来就算要添加新品种的Monster也都
可以调用这个类来判断其周围的情况了。
但是光是这样明显存在很大的缺陷,如果我现在想要扩展一下RouteChecker类,那我就只能打开RouteChecker的代码进行修改,这明显违背了面向对象的基本原则之一:开放封闭原则。为了尽量封闭原本的代码,我引入了简单工厂模式。
以下便是使用了简单工厂模式之后的类图。
对RouteChecker类应用简单工厂模式之后获得的类图
根据这个模型获得代码。
以下是RouteChecker类:
/*路径检查类
功能:
//检查是否已经到达终点
//检查东面是否可行走
//检查南面是否可行走
//检查西面是否可行走
//检查北面是否可行走
*/
#ifndef _ROUTECHECKER_H
#define _ROUTECHECKER_H
#include"maze.h"
/*
类名:RouteChecker
功能:检查路况
*/
class RouteChecker
{
private:
public:
RouteChecker(){};
RouteChecker(Maze * Checked_Maze, int x, int y);
virtual bool Check(){return true;}; //检查
void setCheckedMaze(Maze * ch_Maze) //设置要检查的迷宫
{
checked_Maze = ch_Maze;
};
void setCheckedPosition(int ch_x, int ch_y)//设置要检查的位置
{
checked_x = ch_x;
checked_y = ch_y;
};
// int searchAround(); //搜索四周,以寻找下一个路径点。四个方向东、南、西、北。
//分别返回1、2、3、4,无路可走返回-1,到达终点返回0。
protected:
Maze * checked_Maze;
int checked_x,checked_y;
bool checkWalkable(int x, int y); //检查指定位置是否可行走
};
/*
类名:ExitChecker
功能:检查是否已经到达终点
*/
class ExitChecker : public RouteChecker
{
public:
ExitChecker(){};
bool Check();
};
/*
类名:EastChecker
功能:检查东面是否可行走
*/
class EastChecker : public RouteChecker
{
public:
EastChecker (){};
bool Check();
};
//
//。。。。。略去一些代码
//
/*
类名:NorthChecker
功能:检查北面是否可行走
*/
class NorthChecker : public RouteChecker
{
public:
NorthChecker(){};
bool Check();
};
#endif
/*路径检查类
功能:分别检查各个方向是否可以行走。
*/
#include"routeChecker.h"
RouteChecker::RouteChecker(Maze * Checked_Maze, int x, int y)
{
checked_Maze = Checked_Maze;
checked_x = x;
checked_y = y;
}
/*
功能:检查位置(x,y)是否可行走
*/
bool RouteChecker::checkWalkable(int x, int y)
{
if(checked_Maze->getSquareType(x, y) == '0')
return true;
else
return false;
}
/*
功能:检查是否已经到达终点
*/
bool ExitChecker::Check()
{
if( (checked_Maze->getexit_x() == checked_x) && (checked_Maze->getexit_y() == checked_y) )
{
return true;
}
else
return false;
}
/*
功能:检查东面是否可行走
*/
bool EastChecker::Check()
{
if(checkWalkable(checked_x+1, checked_y))
{
return true;
}
else
return false;
}
//
//。。。。。略去一些
//
/*
功能:检查北面是否可行走
*/
bool NorthChecker::Check()
{
if(checkWalkable(checked_x,checked_y-1))
{
return true;
}
else
return false;
}
以下是工厂类:
/*
类名:RouteCheckerFactory
功能:RouteChecker工厂类,负责创建具体类型的RouteChecker
*/
#ifndef _ROUTECHECKERFACTORY_H
#define _ROUTECHECKERFACTORY_H
#include"routeChecker.h"
class RouteCheckerFactory
{
public:
RouteChecker* Create(int direction);
};
#endif
/*
类名:RouteCheckerFactory
功能:RouteChecker工厂类,负责创建具体类型的RouteChecker
*/
#include"RouteCheckerFactory.h"
RouteChecker* RouteCheckerFactory::Create(int direction)
{
RouteChecker *rc;
switch(direction)
{
case 0: rc = new ExitChecker(); break;//出口
case 1: rc = new EastChecker(); break;//东
case 2: rc = new SouthChecker(); break;//南
case 3: rc = new WestChecker(); break;//西
case 4: rc = new NorthChecker(); break;//北
}
return rc;
};
修改了Explorer类:
{
RouteChecker * rc;
RouteCheckerFactory rcf;
for(int i=0; i<=4; i++)
{
rc = rcf.Create(i);
rc->setCheckedMaze(explored_Maze);
rc->setCheckedPosition(current_x,current_y);
if(rc->Check() == true)
return i;
}
return -1;
}
/* 这几个方法注释掉
bool IsInExit(); //检查是否已经到达终点
bool IsEastWalkable(); //检查东面是否可行走
bool IsSouthWalkable(); //检查南面是否可行走
bool IsWestWalkable(); //检查西面是否可行走
bool IsNorthWalkable(); //检查北面是否可行走
bool checkWalkable(int x, int y); //检查指定位置是否可行走
*/
当然,程序的运行结果跟之前是完全一样的,但是就代码的质量来讲,这是上一个版本所无法比拟的。
做完这一切之后。。。我才发现又囧了searchAround()似乎也应该提取出来封装进RouteChecker.h里才好。而WalkTo()、walkToNext()、walkTowards(int direction)、goBack()这些也应该一并封装才是。
想到这里,我崩溃了。。。要知道我光是封装、测试Routechecker就搞了5个小时啊。。。
Monster还未出现,威老就要挂了!@#¥%……
不行,得想些其他的办法。。。