Design Pattern problem involving N states and transitions between them

后端 未结 6 1388
春和景丽
春和景丽 2020-12-12 16:44

I have a problem at hand and I am not getting which design pattern to use. The problem goes as such:

I have to build a system which has \'N\' states and my system ha

6条回答
  •  北海茫月
    2020-12-12 17:17

    Its clearly a case of a finite-state-machine but its better to combine the conditions rather than create a new condition for each combination. I didn't like the Java example for State pattern on Wikipedia as states know about other states which wouldn't make sense in a lot of scenarios. A transition table that keeps a track of the from state, applicable condition(s), and to state, helps take care of that problem.

    My two cents for an object oriented-finite-state-machine. There are improvements you could do on the OO front, but it gets the idea across.

    class Transition {
        State from;
        Set conditions;
        State to;
    }
    
    class State {
        String state;
    }
    
    class Condition {
        String condition;
    }
    

    The state machine can be constructed with the above types. There is no error checking, but you could throw an exception or something if no next state is found for some conditions.

    class StateMachine {
        List transitions;
        State current;
    
        StateMachine(State start, List transitions) {
            this.current = start;
            this.transitions = transitions;
        }
    
        void apply(Set conditions) {
            current = getNextState(conditions);
        }
    
        State getNextState(Set 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;
        }
    }
    

    And a test run:

    Edit: With some more transitions and new states based on your comment:

    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 transitions = new ArrayList();
    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
    

    I had a bitter experience with using a state machine for a fairly large project. The problem was with composite states. Just like the composite condition you mentioned (sunday and raining), there could technically be composite states which could further be broken down into unit states. This may or may not be the case in your situation, but still worth mentioning. If that is the case, it's best to modify the classical finite state machine and use a set of states instead of a single state to represent the from and to states. If your N is large, this will help keep sanity levels intact. Think hotmail folders vs gmail tags. The transition table would then be presented as

    Transition(Set from, Set conditions, Set to)
    

提交回复
热议问题