Проблема конечного автомата на Java - PullRequest
0 голосов
/ 30 июня 2011

Я хочу реализовать FSM, как показано ниже

  • Первый уровень Самое основное состояние - BASE_STATE. Все состояния происходят из BASE_STATE.
  • Второй уровень , WAITING_STATE, RUNNING_STATE, END_STATE, ... и так далее (Получено из BASE_STATE. Новых нет функциональность)
  • Третий уровень , Есть 2 группы состояния (ACTIVE и PASSIVE), Индивидуальное сопоставление для всех состояний второго уровня как

ACTIVE_WAITING_STATE, ACTIVE_RUNNING_STATE, ACTIVE_END_STATE и т. Д. PASSIVE_WAITING_STATE, PASSIVE_RUNNING_STATE, PASSIVE_END_STATE и т. Д.

большинство функций являются общими для состояний ACTIVE и PASSIVE, только некоторые небольшие функции переопределяются. Там нет проблем, пока здесь. Проблема в том, что все группы третьего уровня имеют общие функции. Я имею в виду, например, я должен реализовать 2 разные функции increment (), одна из которых ACTIVE_xxx_STATEs, другая - PASSIVE_xxx_STATE. Как сделать это без переписывания для всех состояний (например, ACTIVE_WAITING_STATE, ACTIVE_RUNNING_STATE, ACTIVE_END_STATE, а также PASSIVE состояний)

Чтобы прояснить мои вопросы, мой уродливый сын. Проблема в том, что функции приращения одинаковы и переписаны для всех ActivexxxState (а также PassiveXXXState).

public class BaseState {
    // Lots of functions
}

public class WaitingState extends BaseState{
    // Lots of functions
}

public class RunningState extends BaseState{
    // Lots of functions
}

public class EndState extends BaseState{
    // Lots of functions
}

public Class ActiveWaitingState extends WaitingState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}


public Class ActiveRunningState extends RunningState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}

public Class ActiveEndState extends EndState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}

public Class PassiveWaitingState extends WaitingState {
     // Few unique functions        
     private void increment() {
         System.out.println("increment passive");
     }       
}

public Class PassiveRunningState extends RunningState {

     private void increment() {
         System.out.println("increment passive");
     }       
}

public Class PassiveEndState extends EndState {

     private void increment() {
         System.out.println("increment passive");
     }       
}

Ответы [ 3 ]

2 голосов
/ 30 июня 2011

Я бы сделал increment () защищенным методом в BaseState, чтобы он был реализован один раз.


Я написал статью об использовании перечислений для построения конечного автомата . Это может избежать необходимости создавать классы везде для каждого состояния и при этом поддерживать некоторое наследование.


В ответ на ваш комментарий.

abstract class BaseState {
   public abstract boolean isPassive();
   public boolean increment() {
      System.out.println("increment "+(isPassize() ? "passive" : "active");
   }
}

class PassiveState {
   public boolean isPassive() { return true; }
}

Если вы не хотите иметь несколько методов isPassive, вы можете принять соглашение об именах классов

public boolean isPassive() { return getClass().getSimpleName().startsWith("Passive"); }
1 голос
/ 30 июня 2011

Я не уверен, что полностью понял ваш вопрос.В любом случае, я предлагаю вам смоделировать активное / пассивное состояние как свойство в вашем классе, а не использовать наследование.Сделайте вашу иерархию что-то вроде:

public class BaseState {
     boolean active; //active or passive
}

public class WaitingState extends BaseState {

}

...
0 голосов
/ 30 июня 2011

Если вы разделяете обычное поведение на вашем автомате состояний, у вас есть две возможности реализовать это.

1) Вы можете добавить общую реализацию к базовому состоянию, чтобы она могла вызываться любой реализацией состояния, которая наследуется от базового состояния. Видимость этих методов будет защищена .

2) Лучшее решение, по моему мнению, состоит в том, что вы переносите общее поведение в его собственный класс, который вообще не связан с иерархией классов состояний.
Таким образом, вы можете подумать о классе стратегии, который реализует общее поведение и на который ссылается базовый класс, и который может вызываться любым состоянием.
Второе решение лучше, потому что оно повышает тестируемость как конечного автомата, так и класса стратегии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...