java - 涉及 N 个状态和它们之间的转换的设计模式问题

标签 java design-patterns automata state-machine

我手头有一个问题,我不知道要使用哪种设计模式。 问题是这样的:

我必须构建一个具有“N”个状态的系统,并且我的系统必须根据某些条件从任何状态转换到任何其他状态。 前任: 在条件 1 上,从状态 1 移动到 3,在条件 2 上从状态 1 移动到 4。

即使是从一种状态到另一种状态的转换也可以在 2 个或更多不同的条件下完成。

例如,从状态 1 到状态 3 的转换可以在以下情况下完成:
条件1:“今天是星期天”
条件2:“下雨了”
条件 3:“下雨和星期天”
在每种情况下,状态 3 的处理可能不同。

我希望我能够清楚地理解这个问题。请帮忙。

非常感谢

最佳答案

这显然是一个有限状态机的情况,但最好将条件组合起来,而不是为每个组合创建一个新条件。我不喜欢 Wikipedia 上状态模式的 Java 示例,因为状态知道其他状态,这在很多情况下都没有意义。跟踪from 状态、适用条件to 状态的转换表有助于解决该问题。

我为面向对象的有限状态机买了两分钱。您可以在 OO 方面进行一些改进,但它可以让想法得到理解。

class Transition {
    State from;
    Set<Condition> conditions;
    State to;
}

class State {
    String state;
}

class Condition {
    String condition;
}

状态机可以用上述类型构造。没有错误检查,但如果在某些情况下找不到下一个状态,您可以抛出异常或其他东西。

class StateMachine {
    List<Transition> transitions;
    State current;

    StateMachine(State start, List<Transition> transitions) {
        this.current = start;
        this.transitions = transitions;
    }

    void apply(Set<Condition> conditions) {
        current = getNextState(conditions);
    }

    State getNextState(Set<Condition> conditions) {
        for(Transition transition : transitions) {
            boolean currentStateMatches = transition.from.equals(current);
            boolean conditionsMatch = transition.conditions.equals(conditions);
            if(currentStateMatches && conditionsMatch) {
                return transition.to;
            }
        }
        return null;
    }
}

还有一个测试运行:

编辑:根据您的评论添加更多转换和新状态:

State one = new State("one");
State two = new State("two");
State three = new State("three");

Condition sunday = new Condition("Sunday");
Condition raining = new Condition("Raining");
Condition notSunday = new Condition("Not Sunday");
Condition notRaining = new Condition("Not Raining");

List<Transition> transitions = new ArrayList<Transition>();
transitions.add(one, new Set(sunday), three);
transitions.add(one, new Set(sunday), two); // <<--- Invalid, cant go to two and three
transitions.add(one, new Set(raining), three);
transitions.add(one, new Set(sunday, raining), three);
transitions.add(one, new Set(notSunday, notRaining), three);

StateMachine machine = new StateMachine(one, transitions);
System.out.print(machine.current); // "one"
machine.apply(new Set(sunday, raining));
System.out.print(machine.current); // "three

在一个相当大的项目中使用状态机时,我有过痛苦的经历。问题在于复合状态。就像您提到的复合条件(周日和下雨)一样,技术上可能存在复合状态,可以进一步分解为单位状态。在您的情况下可能会或可能不会出现这种情况,但仍然值得一提。如果是这种情况,最好修改经典的有限状态机并使用 状态集 而不是单个状态来表示 from 和 to 状态。如果你的 N 很大,这将有助于保持理智水平不变。想想 hotmail 文件夹与 gmail 标签。然后转换表将显示为

Transition(Set<State> from, Set<Condition> conditions, Set<State> to)

关于java - 涉及 N 个状态和它们之间的转换的设计模式问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2057752/

相关文章:

java - 插入...值...选择。如何使用 INSERT 进行嵌套语句?

java - java编译中未经检查或不安全的操作错误?

design-patterns - 如何在不使用静态/全局变量的情况下实现单例?可能的?

c - 用新字符串替换字符串模式

Python 模式

java - 使用命令提示符在 Windows 中设置 JAVA_OPTS

java不能引用非final变量

finite-automata - Brzozowski 代数方法在此 FA 上的应用

automata - 以下 CFL 和非 CFL 的并集是 CFL 本身吗?