首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用只能在特定情况下使用的操作来表示对象?

如何用只能在特定情况下使用的操作来表示对象?
EN

Software Engineering用户
提问于 2016-03-07 07:46:12
回答 4查看 149关注 0票数 1

假设我正在设计一个RPG类型的游戏,这个游戏有一个基于回合的战斗系统。玩家角色/非玩家角色在战斗内外都可以做一些事情。例如,当他们不在战斗时,他们可以在世界各地移动,使用物品,和其他的npcs交谈,玩家(不是他们的角色)可以打开特定的游戏菜单。当角色在战斗时,他们也可以使用物品,并使用特定的战斗能力,但不能在游戏世界中移动,也不能与其他npcs对话。

这个问题是语言不可知论的,但是示例代码将使用Java。

这的第一个实现可能类似于

代码语言:javascript
运行
复制
public class Character {

    public void use(Item item) { /* ... */ }

    public void talkTo(Npc npc) {
        if (inCombat) {
            throw new IllegalStateException("Unable to talk to npcs while in combat");
        }
        /* ... */
    }

    public void useAbility(Ability ability) {
        if (!inCombat) {
            throw new IllegalStateException("Unable to use ability while not in combat");
        }
        /* ... */
    }
}

我的问题是针对useAbilitytalkTo方法的。这些方法应该一直都是可调用的,还是应该以某种方式加以限制,比如OverworldContextCombatContext,或者某种类型的适配器/代理,以分离可以完成的事情?也许就像

代码语言:javascript
运行
复制
public class OverworldCharacter extends Character {

    private Character character;

    public OverworldCharacter(Character character) {
        this.character = character;
    }

    public void talkTo(Npc npc) {
        // do some stuff
    }

    // proxy character methods to field
}

代码语言:javascript
运行
复制
public class InCombatCharacter {

    // Same as other class

    public void useAbility(Ability ability) {
        // do some more stuff
    }
}

这个游戏的目的是允许第三方创建插件/mods,所以这是在这个设计中需要考虑的另一件事情。

EN

回答 4

Software Engineering用户

发布于 2016-03-07 08:27:08

您可以在您的角色上使用表示角色所采取的操作的方法,这些方法会导致“上下文”,其中的操作是有限的。这样,只有在相关的情况下才能调用这些操作。

不以任何方式限制来自域的操作的问题是,您的检查逻辑将被复制很多。您添加的每个操作都需要检查字符所在的“上下文”。一次被遗忘的检查会导致一个角色在战斗中使用出战斗能力。即使您永远不会忘记添加检查,您也会面临大量的代码,这些代码不是在编译时检查的,而是在运行时检查的。

代码语言:javascript
运行
复制
public class Character 
{
    public BattleRound fight(Enemy npc) 
    {
        return new BattleRound(this, npc);
    }
}

public class BattleRound
{
    public void useAbility(CombatAbility ability)
    {
        /*...*/
    }
}

上面的例子让你的角色在与敌人作战时进入一轮战斗。角色可以在一轮内使用异能,攻击,施法术.这些操作由BattleRound (或者BattleTurn )强制执行(如果您喜欢这个术语的话)。这种设计的另一个优点是,您甚至可以根据类限制操作:WizardCharacter可以返回一个WizardBattleRound,它不允许hit,但确实允许castheal。动作对圆的影响可以对角色执行动作,如减少命中点、增加命中点、添加一定的法术效果等。

票数 2
EN

Software Engineering用户

发布于 2016-03-07 08:28:50

当您可以忽略这些“无效”调用时,为什么要抛出错误。

除非你的目标是教开发人员,你的界面的用户,正确的协议,你可能想离开直接用户界面书籍。

直接用户界面(汽车中的方向盘和加速器就是直接用户界面的例子)只会忽略无效的使用--如果上下文不正确,什么也不做。

你可以随心所欲地按下油门,但除非汽车的引擎开着,否则什么都不会发生(除了你把发动机淹死在燃料里)。当汽车的引擎开着,汽车在齿轮上,离合器被抓住时,你可以去某个地方。除非有人也站在休息时间。

大多数人非常有效地处理这种界面。

票数 1
EN

Software Engineering用户

发布于 2016-03-07 08:49:15

您正在尝试根据系统的当前状态决定允许哪些操作。

对此建模的一种方法是使用状态图状态图

使用有限状态机状态设计模式在代码中表示状态图的方法是存在的。

在这种情况下,您可能首先要查看状态图/图表,它将使您了解如何提出您的国家,如何从一种状态过渡到下一种状态,以及如何合并操作。有了这些知识,您可以使用状态设计模式将其构建到您的程序中。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/311957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档