序言:我用C++制作了一个简单的棋盘游戏,AI角色在棋盘上移动方格。有不同类型的方块,每个从抽象类继承,每个对AI字符有不同的影响。例如,有些是人物可以买东西的商店,另一些是人物赚钱的工作场所。
同样,还有不同的AI字符(也是从抽象类继承的),它们做出不同的决定。有些人工作比其他人多,有些人吃得比别人多,等等。
问题是AI字符需要知道方型,才能决定要做什么。目前,使用类型名称字符串作为成员变量来检查类型是最简单的解决方案,但在添加新类型的方块和AI字符时,它感觉非常不优雅,也没有多大帮助。
问:通过询问对象的标识符来检查对象的类型是否是一种错误的做法?使用其他运行时类型识别方法(如dynamic_cast和typeinfo )来控制执行流程是否是一种糟糕的做法?
示例:在Square类下面(通过currentSquare()访问)有一个成员函数getType(),它返回一个具有类型名称的字符串:
//Normal AI character
void decide() {
if(currentSquare()->getType()=="HOME") {
watchTV();
sleep();
}
if(currentSquare()->getType()=="WORKPLACE") {
work();
}
}
//Party animal AI
void decide() {
if(currentSquare()->getType()=="HOME") {
moveTo(getGameBoard()->closestBar());
}
if(currentSquare()->getType()=="WORKPLACE") {
sleep();
}
}
发布于 2013-10-14 21:37:36
正如Amon所指出的,这是访客模式的一个很好的应用程序。使用它,您的AI类最终会看起来如下所示:
void decide(HomeSquare square);
void decide(WorkSquare square);
void decide(ShopSquare square);
您的方块有一个accept
函数,看起来如下:
void accept(AI ai)
{
ai.decide(this);
}
这允许您使用继承来创建适当的默认值,或者强制每个AI实现某些决策。例如,除了在家里,您可以创建一个与另一个AI完全相同的AI,而不需要复制一堆代码。编译器会指出您忘记了什么地方,而不必到处抛出。
发布于 2013-10-14 19:54:03
对于这种情况,我更喜欢使用枚举而不是字符串,并且应该编写"check type“代码来排除未指定的情况。
switch (currentSquare()->getType())
{ default: BUG("case not expected");
case workplace: ...
break;
case home: ..
break;
}
发布于 2013-10-14 22:59:04
我想指出使用字符串标识对象类的脆弱性。您在某种程度上是围绕类型安全性工作的,如果出了问题,您可能会在运行时收到奇怪的错误。如果您有相当多的类,您需要检查,如果您引入一个新类或删除另一个类,那么更新代码的所有部分可能会很痛苦。此外,它使静态分析复杂化,甚至阻止静态分析,从而降低了自动查找bug(如死代码)的可能性。
将此与使用其他人已经指出的访问者模式进行比较。您将获得类型安全性和(如果出错)编译时错误。更重要的是,访问者模式为您提供了更多的灵活性,并且您不会得到长时间的级联if-else块或开关块,从而提高了可读性和可维护性。静态分析工具将按预期工作。
因此,我认为使用成员变量进行识别是最优的。
完全公开:我主要是一个java开发人员,但我认为在这种情况下,java和c++之间的差异并不重要。如果我错了,请纠正我。;)
https://softwareengineering.stackexchange.com/questions/214404
复制相似问题