涉及 N 个状态及其之间转换的设计模式问题

我手头有一个问题,我没有得到要使用的设计模式。问题是这样的:

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

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

例如,在以下情况下,可以从状态 1 过渡到状态 3:条件
1:“它是星期日”
条件 2:“下雨”
条件 3:“下雨和星期日”
在每个条件中,状态 3 处的处理可以不同。

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

多谢


答案 1

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

我为面向对象的有限状态机准备的两分钱。您可以在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

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

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

答案 2

这听起来像是有限状态机的典型用法。

简而言之,状态机描述了系统可以处于的各种状态,以及在哪些条件下它可以从一个状态转到另一个状态。状态机的描述与您的英文描述完全相同。它可以使用状态图正式描述

在代码中,你可以创建一个这样的状态机:

 enum State { Init, ShowMenu, ShowMsg, DisplayVideo, Exit };
 State state = State.Init;

 while (state != State.Exit)
 {
      switch(state)
      {
           case State.Init:
                init();
                state = State.ShowMenu;
                break;
           case State.ShowMenu:
                if(lastMenuItemSelected==1) state = State.ShowMsg;
                if(lastMenuItemSelected==2) state = State.DisplayVideo;
                break;
           case State.ShowMsg:
                ....
                break;
           ....
 }

我不确定我是否得到了Java的确切语法正确...我更喜欢C#


推荐