You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现车库门控制器以跟踪其上次运动方向?

解决Killer Garage Door中暂停恢复原方向的状态模式实现思路

我之前在做类似的状态模式实践时也踩过方向跟踪的坑,结合你的需求,给你几个具体的落地思路和代码示例,应该能解决你JUnit测试失败的问题:


1. 先在上下文类中维护核心状态变量

首先在你的GarageDoor(上下文类)里添加两个关键变量:一个枚举类型记录运动方向,一个字段跟踪上次的运动方向,同时还要记录门的当前位置(因为暂停后需要从当前位置继续运动):

// 定义方向枚举
public enum DoorDirection {
    UP, DOWN, STOPPED
}

public class GarageDoor {
    private DoorState currentState;
    private DoorDirection lastDirection;
    private int currentPosition; // 0=完全关闭,100=完全打开

    public GarageDoor() {
        // 初始状态:关闭,方向停止,位置0
        currentState = new ClosedState();
        lastDirection = DoorDirection.STOPPED;
        currentPosition = 0;
    }

    // 提供状态和方向的访问/修改方法
    public void setState(DoorState newState) {
        this.currentState = newState;
    }

    public void setLastDirection(DoorDirection direction) {
        this.lastDirection = direction;
    }

    public DoorDirection getLastDirection() {
        return lastDirection;
    }

    public void updatePosition(int delta) {
        currentPosition = Math.max(0, Math.min(100, currentPosition + delta));
        // 到达边界时自动切换状态(比如到100时切换到OpenState)
        if (currentPosition == 100) {
            setState(new OpenState());
            setLastDirection(DoorDirection.STOPPED);
        } else if (currentPosition == 0) {
            setState(new ClosedState());
            setLastDirection(DoorDirection.STOPPED);
        }
    }

    // 外部触发的按钮和障碍物检测方法
    public void pressButton() {
        currentState.pressButton(this);
    }

    public void detectObstacle() {
        currentState.detectObstacle(this);
    }
}

2. 在各状态类中处理方向更新与恢复逻辑

状态模式的核心是每个状态类只负责自己的行为,我们需要在状态切换时同步更新lastDirection,重点处理暂停状态的恢复逻辑

示例1:关闭状态(ClosedState)

public class ClosedState implements DoorState {
    @Override
    public void pressButton(GarageDoor door) {
        door.setState(new OpeningState());
        door.setLastDirection(DoorDirection.UP);
        // 启动开门计时逻辑(比如每秒调用updatePosition(20),5秒到100)
    }

    @Override
    public void detectObstacle(GarageDoor door) {
        // 关闭状态下遇障碍物无需处理
    }
}

示例2:开门状态(OpeningState)

public class OpeningState implements DoorState {
    @Override
    public void pressButton(GarageDoor door) {
        // 运动中按按钮→切换到暂停状态,保留上次方向UP
        door.setState(new PausedState());
    }

    @Override
    public void detectObstacle(GarageDoor door) {
        // 遇障碍物立即反转方向→切换到关门状态,更新方向为DOWN
        door.setState(new ClosingState());
        door.setLastDirection(DoorDirection.DOWN);
    }
}

关键:暂停状态(PausedState)的恢复逻辑

这是解决你问题的核心,按下按钮时根据lastDirection回到对应的运动状态:

public class PausedState implements DoorState {
    @Override
    public void pressButton(GarageDoor door) {
        DoorDirection lastDir = door.getLastDirection();
        if (lastDir == DoorDirection.UP) {
            door.setState(new OpeningState());
            // 恢复开门计时,从当前位置继续
        } else if (lastDir == DoorDirection.DOWN) {
            door.setState(new ClosingState());
            // 恢复关门计时,从当前位置继续
        }
        // 初始停止状态下按按钮的情况,可根据需求补充
    }

    @Override
    public void detectObstacle(GarageDoor door) {
        // 暂停时遇障碍物,可直接反转方向(比如从暂停的关门状态转为开门)
        door.setLastDirection(door.getLastDirection() == DoorDirection.UP ? DoorDirection.DOWN : DoorDirection.UP);
        pressButton(door); // 触发恢复逻辑,直接按新方向运动
    }
}

3. 修复JUnit测试的方向问题

那些标记→的测试用例,本质是暂停恢复时方向判断错误。现在通过lastDirection的跟踪,PausedState能精准回到之前的运动方向:

  • 比如测试用例:开门中→按按钮暂停→再按按钮,现在会继续开门而不是关门
  • 遇障碍物的测试:关门中→检测到障碍物→反转开门,方向会正确更新为UP

内容的提问来源于stack exchange,提问作者Yone

火山引擎 最新活动