Паттерн государственного проектирования: как избежать дублирования кода при использовании entry () и exit ()?

Ситуация: Мои состояния имеют методы entry() и exit(), которые необходимо вызывать каждый раз при переходе состояния. Чтобы убедиться в этом, я использовал метод changeState() в State, который содержит необходимую процедуру. Он вызывается контекстом каждый раз, когда он использует операцию с участием конечного автомата. Однако проблема в том, что мне нужно вызывать state.changeState() каждый раз, когда я добавляю новый метод, и я уверен, что есть способ избежать дублирования кода. Ниже приведен код для дальнейшего пояснения.

class Context {
    State state;

    void method1() {
        state.method1();
        state.changeState();
    }

    void method2() {
        state.method2();
        state.changeState(); // Code duplication!!
}

abstract class State {
    Context context;
    State next;

    void changeState() {
        this.exit();
        next.entry();
        context.setState(next);
    }
    // other necessary methods
}

class ConcreteState extends State {
    void method1() {
        // do something
        next = AnotherConcreteState;
    }
    void entry() {/*do something */};
    void exit() {/*do something */};
}

Если я хочу добавить дополнительные методы в Context, что я могу сделать, чтобы избежать дублирования кода вызова state.changeState() каждый раз внутри новых методов?

1 ответ

Решение

Вы очень близки. ВchangeState метод принадлежит к Context класс, а не Stateкласс. Вот хорошая статья по теме. Обратите внимание, что диаграмма классов показываетchangeState в Document (контекст) класс.

Чтобы было еще чище, changeState мог взять nextсостояние как параметр. Как это:

class Context {
  State state;

  void method1() {
    state.method1();
  }

  void changeState(next) {
    state.exit();
    this.state = next;
    state.enter();
  }
}

abstract class State {
  Context context;

  // other methods
}

class ConcreteState extends State {
  void method1() {
    // do something
    context.changeState(AnotherConcreteState);
  }

  void enter() { /* do something */ }
  void exit() { /* do something */ }
}

Теперь, когда вы добавляете больше методов в Context, нет дублирования в Context. Это выглядело бы так:

class Context {
  State state;

  void method1() {
    state.method1();
  }

  void method2() {
    state.method2();
  }

  void changeState(next) {
    state.exit();
    this.state = next;
    state.enter();
  }
}

abstract class State {
  Context context;

  // other methods
}

class ConcreteState extends State {
  void method1() {
    // do something
    context.changeState(AnotherConcreteState);
  }

  void method2() {
    // do something else
    context.changeState(YetAnotherConcreteState);
  }

  void enter() { /* do something */ }
  void exit() { /* do something */ }
}
Другие вопросы по тегам