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

Ситуация: Мои состояния имеют методы 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 Ответ

0 голосов
/ 07 августа 2020

Вы очень близки. Метод changeState принадлежит к классу Context, а не к классу State. Вот хорошая статья по топи c. Обратите внимание, что диаграмма классов показывает 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 */ }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...