2013-12-06 3 views
2

Я столкнулся с некоторыми примерами состояний машин, написанными как перечисления. Например:Сцепление в перечислениях

public enum State { 
    INITIAL { 
     @Override 
     public State process(char ch) { return MIDDLE; } 
    }, 

    MIDDLE { 
     @Override 
     public State process(char ch) { 
      switch (ch) { 
       case 'a': return INITIAL; 
       default: return FINAL; 
      } 
     } 
    }, 

    FINAL { 
     @Override 
     public State process(char ch) { return FINAL; } 
    }; 

    public abstract State process(char ch); 

    public static State initial() { return INITIAL; } 
} 

Что касается меня, то есть константы знают друг друга. Их реализации могут быть изменены, и если константы добавляются (или удаляются), подразумеваются дополнительные изменения.

Однако все изменения содержатся в перечислении, если только внешний код не ссылается на константы напрямую и не делает предположений о таблице переходов.

Таким образом, этот код сильно связан, слабо связан, или он субъективный?

+0

Да, я мог видеть отдельный класс трюмов логики переходов состояний, а не охватывает, что в перечислении. – GriffeyDog

+0

@GriffeyDog Перечисление может быть закрытым и вложенным внутри некоторого класса, который представляет собой правильный экземпляр конечного автомата. Итак, я предполагаю, что это сокращенная версия действий и, вероятно, не является хорошей практикой в ​​любом серьезном коде. – afsantos

ответ

2

Я бы сказал, что это слишком плотно соединено для гибкого инструмента.

Что-то свободнее было бы гораздо более гибким:

public enum State { 
    INITIAL, 
    MIDDLE, 
    FINAL; 
    public static State initial() { 
    return INITIAL; 
    } 

} 

// A 'null' for the Character matches anything. 
static Map<Pair<State,Character>, State> machine = new HashMap<>(); 
static { 
    // Always transit from INITIAL to MIDDLE 
    machine.put(new Pair<State,Character>(State.INITIAL,null), State.MIDDLE); 
    // An 'a' transitrs us to FINAL 
    machine.put(new Pair<State,Character>(State.MIDDLE,'a'), State.FINAL); 
    // Anything else takes us back to INITIAL 
    machine.put(new Pair<State,Character>(State.MIDDLE,null), State.FINAL); 
    // Stay in FINAL once there. 
    machine.put(new Pair<State,Character>(State.FINAL,null), State.FINAL); 

} 
+0

Это незначительно, но почему вы решили добавить метод 'initial()' factory? –

+0

@PaulBellora - Это было в оригинале, и это казалось хорошей идеей - начальное состояние системы не обязательно должно определяться машиной, ее можно определить по списку состояний. По дальнейшей мысли, что, возможно, были неправильными, но я не думаю, что это было неправильно. – OldCurmudgeon

+0

А я пропустил это в фрагменте OP. Понял. –