Есть ли преимущество использования enum в FSM по сравнению с использованием только строки? - PullRequest
0 голосов
/ 30 января 2019

Я хочу создать конечный автомат, и большая часть кода, который я могу найти, использует перечисления, и мне было просто интересно, дает ли это преимущество по сравнению с использованием строки или int для хранения состояния.

С Enum:

класс TrafficLight {enum State {RED, YELLOW, GREEN};

State state = State.GREEN;

public void iterate() throws InterruptedException {
    switch (this.state) {
    case RED:
        System.out.println("RED");
        Thread.sleep(1000);
        this.state = State.GREEN;
        break;

    case GREEN:
        System.out.println("GREEN");
        Thread.sleep(1000);
        this.state = State.YELLOW;
        break;

    case YELLOW:
        System.out.println("YELLOW");
        Thread.sleep(1000);
        this.state = State.RED;
        break;
    }

}

открытый класс Main {

public static void main(final String[] args) throws InterruptedException {

    final TrafficLight a = new TrafficLight();
    while (true) {
        a.iterate();
    }
}

}

С String

открытый класс TrafficLight {

String state = "GREEN";

public void iterate() throws InterruptedException {
    switch (state) {
        case "RED":
            System.out.println("RED");
            Thread.sleep(1000);
            state = "GREEN";
            break;

        case "GREEN":
            System.out.println("GREEN");
            Thread.sleep(1000);
            state = "YELLOW";
            break;

        case "YELLOW":
            System.out.println("YELLOW");
            Thread.sleep(1000);
            state = "RED";
            break;
    }
}

}

(оба используют один и тот же метод main)

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

Спасибо.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Основное преимущество для Enum над String: более конкретно оно набрано, поскольку Enum указывает возможные значения.
Это делает ваш код более надежным и лучше документированным.
Для FSM и болееобычно ограниченные значения, это то, что вы ищете.
Но для проблем / областей, где возможные значения определены во время выполнения, а не во время компиляции (извлечение из базы данных или что-то еще), Enum не лучший кандидат.

Пример интереса Enum в вашем случае

При использовании Enum он не будет компилироваться, поскольку REDD не объявлено в классе перечисления State:

case REDD:
    System.out.println("RED");
    Thread.sleep(1000);
    this.state = State.GREEN;
    break;

Но с String он будет компилироваться и просто не будет работать должным образом:

case "REDD":
    System.out.println("RED");
    Thread.sleep(1000);
    state = "GREEN";
    break;

Перечисляемые значения являются экземплярами класса enum с собственными значениями для полей экземпляров, но также с переопределением способностей.например, методы

Это еще одно преимущество enum в FSM или любом домене, где перечисляемые значения связаны с конкретными свойствами / обработками и где в соответствии с перечисляемым значением значения полей или поведение метода могутотличаются.

Например, здесь мы указываем поведение для получения следующего перехода:

enum State {
    YELLOW(){
        @Override
        public State next() {
            return RED;
        }
    },
    RED(){
        @Override
        public State next() {
            return GREEN;
        }
    },
    GREEN(){
        @Override
        public State next() {
            return YELLOW;
        }
    };
    public abstract State next();
}

Теперь перечисление содержит достаточно логики, чтобы оператор switch больше не требовался:

public void iterate() throws InterruptedException {
    System.out.println(state);
    Thread.sleep(1000);         
    state = state.next();
}
0 голосов
/ 30 января 2019

Перечисление имеет определенное преимущество перед String или Integer / int, поскольку оно может содержать дополнительную информацию о состояниях, которые вы используете в своем FSM.Рассмотрим следующее расширение вашего перечисления состояний, которое содержит отображаемое значение пользовательского интерфейса:

public enum State {

   RED("My Red"),
   YELLOW("My Yellow"),
   GREEN("My Green");

   private String uiValue;

   private State(String uiValue) {
       this.uiValue = uiValue;
   }

   public String getUiValue() {
       return uiValue;
   }

}

Использование String или int означает, что вам придется использовать значения «Magic» для представления своих состояний.Напротив, перечисление - это элегантный способ описания состояний - это группа значений в одном контексте, и сравнение перечислений проще и элегантнее, чем сравнение строк.

...