Это явно случай конечного автомата, но лучше комбинировать условия, а не создавать новые условия для каждой комбинации. Мне не понравился пример Java для шаблона State в Википедии, поскольку государства знают о других состояниях, которые не имеют смысла во многих сценариях. Таблица переходов, которая отслеживает состояние из , применимые условия и состояния от до , помогает решить эту проблему.
Мои два цента за объектно-ориентированный конечный автомат. Есть улучшения, которые вы могли бы сделать на фронте 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)