如果目标状态不是下一个,则使用哪种状态机设计?

Jos*_*eon 2 java design-patterns state-machine

我一直在阅读状态机,因为它可能需要用于我的下一个项目.我在网上找到的大多数例子都显示了如何从StateA转到StateB.但是如果你的下一个想要的状态不是一个相邻的状态呢?是否有任何共同的模式/实践来实现这一目标?理想情况下是Java,但我也可以阅读其他编程语言.

# Example States
WakeUp->Get Dressed->Get Car Keys->Get in Car->Drive to Work->Work

Current State: Get in Car
Run Code Online (Sandbox Code Playgroud)

要解决的问题

# Scenario 1: Desired State == Work
Forgot car keys, so you have to return to previous state and then move forward in states again.

# Scenario 2: Desired State == Work
Have car keys, so move forward in states to get to Desired State.
Run Code Online (Sandbox Code Playgroud)

状态机很可能不会优雅地解决这个问题,我只需要手工制作逻辑,我不介意,但我想我会遵循一个共同的设计模式来帮助其他人理解它.

从上面的例子中,我不需要担心"内部"状态,这对于我正在处理的项目也是如此; 以防万一在可能的解决方案中有所作为.

fla*_*kes 5

这是一种定义状态机的简单方法.

在枚举中定义所需的所有状态.

enum StateType {
   WAKE_UP, GET_DRESSED, GET_CAR_KEYS, GET_IN_CAR, DRIVE_TO_WORK, WORK
}
Run Code Online (Sandbox Code Playgroud)

拥有一个控制状态的状态机,以及一个对状态机执行操作的状态接口.州然后返回下一个要去的州.

interface State {
    StateType next(StateMachine sm);
}
Run Code Online (Sandbox Code Playgroud)

为多种类型实现此状态

class GetInCarState implements State {
    @Override
    public StateType next(StateMachine  sm) {
        if (sm.hasKeys()) {
            return StateType.DRIVE_TO_WORK;
        }
        return StateType.GET_CAR_KEYS;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在定义状态机

class StateMachine {
    private Map<StateType, State> states = new HashMap<StateType, State>() {{
        put(StateType.WAKE_UP, new WakeUpState()); 
        put(StateType.GET_DRESSED, new GetDressedState()); 
        put(StateType.GET_CAR_KEYS, new GetCarKeysState()); 
        put(StateType.GET_IN_CAR, new GetInCarState()); 
        put(StateType.DRIVE_TO_WORK, new DriveToWorkState()); 
        put(StateType.WORK, new WorkState()); 
    }};

    private StateType currentState = StateType.WAKE_UP;

    private boolean hasCarKeys;

    public boolean hasKeys() {
        return hasCarKeys;
    }

    public void setHasKeys(boolean hasKeys) {
        hasCarKeys = hasKeys;
    }

    public void update() {
        currentState = states.get(currentState).next(this);
    }
}
Run Code Online (Sandbox Code Playgroud)