如何将状态转换值限制为仅Java中的有效值?

Adh*_*mik 4 java algorithm design-patterns

我必须实现状态转换验证,例如:

'P' -> 'W' -> 'M' -> 'F' -> 'G'
'P' -> 'I' -> 'B' -> 'M' -> 'F' -> 'G'
Run Code Online (Sandbox Code Playgroud)

其中"->"表示"可以移动到"

简而言之,特定状态只能转移到某种状态,而不能转移到其他状态.如上例所示,P可以移动到W或I,但不能移动到任何其他状态.

注意:系统中的状态数量有限.

我读过有关策略模式的内容,但我并不认为这个特殊问题适合它.在Java 8中实现这一点的最佳方法是什么?

Bor*_*der 5

我的建议是编写一个enum State代表每个可用状态和有效转换的代码:

enum State {
    G(Collections.emptySet()),
    F(Collections.singleton(G)),
    M(Collections.singleton(F)),
    B(Collections.singleton(M)),
    I(Collections.singleton(B)),
    W(Collections.singleton(M)),
    P(new HashSet<>(Arrays.asList(W, I)));

    private final Set<State> validTransitions;

    State(final Set<State> validTransitions) {
        this.validTransitions = validTransitions;
    }

    public State transitionTo(final State next) {
        if(!validTransitions.contains(next)) {
            throw new IllegalStateException();
        }
        return next;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:

这将只允许DAG状态转换,如果您引用尚未声明的Statein validTransitions,那么您将得到" 非法转发引用 "编译器错误.

我认为这是一个优点,因为它会在编译时强制执行一组有效的状态,但前提是你的状态是非循环的.


如果您使用的是Java 9+

enum State {
    G(Collections.emptySet()),
    F(Set.of(G)),
    M(Set.of(F)),
    B(Set.of(M)),
    I(Set.of(B)),
    W(Set.of(M)),
    P(Set.of(W, I));

    private final Set<State> validTransitions;

    State(final Set<State> validTransitions) {
        this.validTransitions = validTransitions;
    }

    public State transitionTo(final State next) {
        if(!validTransitions.contains(next)) {
            throw new IllegalStateException();
        }
        return next;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @GhostCat - 你不能拥有不变性和它看起来的'EnumSet`; 那么这是一个优先事项 - 你想要一个不可变的`enum`或者使用`EnumSet`.最不开心的权衡. (2认同)