处理异常时如何避免代码部分执行?Java文本冒险拾取操作原子性问题
文字冒险游戏take操作原子性实现方案
- 方案1:前置校验优先执行
先调用两个操作的校验接口确认可执行,全部通过后再执行实际变更,从根源上避免中途失败的问题。适合Location和Inventory类可扩展校验方法的场景。
示例代码:
public void take(Item item) throws ActionException { // 先做所有前置校验,不执行实际变更 if (!location.canRemove(item)) { throw new ActionException("物品不在当前位置,无法拾取"); } if (!inventory.canAdd(item)) { throw new ActionException("背包容量不足或物品无法拾取"); } // 校验全部通过后执行实际操作 location.remove(item); inventory.add(item); }
- 方案2:异常捕获+回滚机制
如果现有类没有提供单独的校验方法,可以用try-catch包裹后续操作,失败时回滚已执行的步骤。需要保证回滚操作本身的稳定性,避免回滚也失败导致更严重的问题。
示例代码:
public void take(Item item) throws ActionException { location.remove(item); try { inventory.add(item); } catch (ActionException e) { // 拾取失败,把物品放回原位置回滚 location.add(item); // 重新抛出原异常给上层处理 throw e; } }
- 方案3:通用事务封装(适合多操作原子性场景多的项目)
如果项目中存在大量需要多步原子执行的逻辑(比如交易、道具合成等),可以抽象事务操作接口统一管理:
interface TransactionalAction { void execute() throws ActionException; void rollback(); } // 移除物品操作实现类 class RemoveItemAction implements TransactionalAction { private Location location; private Item item; // 构造方法省略 public void execute() throws ActionException { location.remove(item); } public void rollback() { location.add(item); } } // 添加物品操作实现类 class AddItemAction implements TransactionalAction { private Inventory inventory; private Item item; // 构造方法省略 public void execute() throws ActionException { inventory.add(item); } public void rollback() { inventory.remove(item); } } // 最终执行逻辑 public void take(Item item) throws ActionException { List<TransactionalAction> actions = Arrays.asList( new RemoveItemAction(location, item), new AddItemAction(inventory, item) ); int executedCount = 0; try { for (TransactionalAction action : actions) { action.execute(); executedCount++; } } catch (ActionException e) { // 逆序回滚已执行的操作 for (int i = executedCount - 1; i >= 0; i--) { actions.get(i).rollback(); } throw e; } }
补充说明:如果拾取操作的失败概率中,背包不可拾取的概率远高于物品不存在的概率,可以调整执行顺序,先执行inventory.add相关操作再执行location.remove,减少回滚触发的概率。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

