2016-09-29 67 views
2

我一直在reading up on State Machines,因为它可能需要用于我的下一个项目。我在网上找到的大多数例子都展示了如何从StateA转到StateB。但是如果你的下一个想要的状态不是邻接状态呢?是否有任何共同的模式/做法来实现这一目标?理想情况下在Java中,但我也可以阅读其他编程语言。如果您的目标状态不是下一个状态,那么应使用哪种状态机设计?

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

Current State: Get in Car 

问题解决

# 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. 

这很可能是国机可能无法完美地解决这个问题,我只是需要手工工艺的逻辑,我不介意,但认为我会d遵循一种通用的设计模式来帮助他人理解它。

从上面的例子中,我不必担心'内部'状态,这对我正在处理的项目也是如此;以防万一在可能的解决方案中发挥作用。

回答

4

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

在枚举中定义所有你想要的状态。

enum StateType { 
    WAKE_UP, GET_DRESSED, GET_CAR_KEYS, GET_IN_CAR, DRIVE_TO_WORK, WORK 
} 

有无,其控制状态的的statemachine,并且执行对的statemachine的动作的状态的界面。状态然后返回到下一个状态。

interface State { 
    StateType next(StateMachine sm); 
} 

多种类型

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

实现这种状态现在定义状态机

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); 
    } 
} 
+0

尼斯之一。几个建议:(1)StateType.DriveToWork - 你可能意味着DRIVE_TO_WORK; (2)通过在enum类型中移动next方法将'GetInCarState'和'StateType.DRIVE_TO_WORK'结合起来就可以实现你的例子 - 它将消除任何需要通过StateType进行映射的情况。 – bashnesnos

+0

谢谢(1):)对于第二;我也在考虑让枚举定义'next'方法,但决定不采用这种方法。通过不将实现耦合到枚举中,每个状态可以有多个表示。这可能有助于为测试创建模拟状态,并可以在以后创建类似的状态机而无需创建全新的枚举。 – flakes

+1

是的,这是所有OOP时间的大问题 - 抽象或不抽象:-)看起来你更喜欢首先抽象:-) – bashnesnos