State Design Pattern: 在使用entry()和exit()时如何避免代码重复?

huangapple go评论82阅读模式
英文:

State Design Pattern: How to avoid code duplication when using entry() and exit()?

问题

Situation: 我的状态类(State)具有需要在状态转换时调用的entry()和exit()方法。为确保这一点,我在State类中使用了一个changeState()方法,其中包含必要的过程。它由上下文(Context)在涉及状态机的操作时每次调用。然而,问题在于,每次添加新方法时,我都需要调用state.changeState(),我确信有一种方法可以避免这种代码重复。以下是进一步说明的代码:

class Context {
    State state;

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

    void method2() {
        state.method2();
        state.changeState(); // 代码重复!
    }

    // 其他方法
}

abstract class State {
    Context context;
    State next;

    void changeState() {
        this.exit();
        next.entry();
        context.setState(next);
    }

    // 其他必要的方法
}

class ConcreteState extends State {
    void method1() {
        // 做一些事情
        next = AnotherConcreteState;
    }

    void entry() {/* 做一些事情 */}
    void exit() {/* 做一些事情 */}
}

如果我想在Context中添加额外的方法有什么方法可以避免在新方法中每次调用state.changeState()时出现代码重复
英文:

Situation: My States have an entry() and exit() method that needs to be called every time when a State transitions. To ensure that, I used a changeState() method in State that contains the necessary procedure. It is called by the Context every time it uses an operation involving the state machine. The problem however, is that I need to call state.changeState() every time when I add a new method and I'm sure there's a way to avoid that code duplication. Below is code for further clarification

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 */};
}

If I want to add additional methods in Context, what can I do to avoid code duplication of calling state.changeState() every time inside the new methods?

答案1

得分: 2

你已经非常接近了。changeState 方法应该属于 Context 类,而不是 State 类。这里有一篇关于这个主题的好文章。请注意,类图中显示 changeStateDocument(上下文)类中。

为了使代码更清晰,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;

  // 其他方法
}

class ConcreteState extends State {
  void method1() {
    // 做一些事情
    context.changeState(AnotherConcreteState);
  }

  void enter() { /* 做一些事情 */ }
  void exit() { /* 做一些事情 */ }
}

现在,当你向 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;

  // 其他方法
}

class ConcreteState extends State {
  void method1() {
    // 做一些事情
    context.changeState(AnotherConcreteState);
  }

  void method2() {
    // 做一些其他事情
    context.changeState(YetAnotherConcreteState);
  }

  void enter() { /* 做一些事情 */ }
  void exit() { /* 做一些事情 */ }
}
英文:

You are very close. The changeState method belongs in the Context class, not the State class. Here's a good article on the topic. Note that the class diagram shows changeState in the Document (context) class.

To make it even cleaner, changeState could take the next state as a parameter. Like this:

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 */ }
}

Now, as you add more methods to Context, there is no duplication in Context. It'd look like this:

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 */ }
}

huangapple
  • 本文由 发表于 2020年8月4日 19:03:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63245531.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定