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

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

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

问题

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

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. state.changeState();
  6. }
  7. void method2() {
  8. state.method2();
  9. state.changeState(); // 代码重复!
  10. }
  11. // 其他方法
  12. }
  13. abstract class State {
  14. Context context;
  15. State next;
  16. void changeState() {
  17. this.exit();
  18. next.entry();
  19. context.setState(next);
  20. }
  21. // 其他必要的方法
  22. }
  23. class ConcreteState extends State {
  24. void method1() {
  25. // 做一些事情
  26. next = AnotherConcreteState;
  27. }
  28. void entry() {/* 做一些事情 */}
  29. void exit() {/* 做一些事情 */}
  30. }
  31. 如果我想在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

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. state.changeState();
  6. }
  7. void method2() {
  8. state.method2();
  9. state.changeState(); // Code duplication!!
  10. }
  11. abstract class State {
  12. Context context;
  13. State next;
  14. void changeState() {
  15. this.exit();
  16. next.entry();
  17. context.setState(next);
  18. }
  19. // other necessary methods
  20. }
  21. class ConcreteState extends State {
  22. void method1() {
  23. // do something
  24. next = AnotherConcreteState;
  25. }
  26. void entry() {/*do something */};
  27. void exit() {/*do something */};
  28. }

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 状态作为参数,像这样:

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. }
  6. void changeState(next) {
  7. state.exit();
  8. this.state = next;
  9. state.enter();
  10. }
  11. }
  12. abstract class State {
  13. Context context;
  14. // 其他方法
  15. }
  16. class ConcreteState extends State {
  17. void method1() {
  18. // 做一些事情
  19. context.changeState(AnotherConcreteState);
  20. }
  21. void enter() { /* 做一些事情 */ }
  22. void exit() { /* 做一些事情 */ }
  23. }

现在,当你向 Context 添加更多方法时,不会在 Context 中出现重复。它将如下所示:

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. }
  6. void method2() {
  7. state.method2();
  8. }
  9. void changeState(next) {
  10. state.exit();
  11. this.state = next;
  12. state.enter();
  13. }
  14. }
  15. abstract class State {
  16. Context context;
  17. // 其他方法
  18. }
  19. class ConcreteState extends State {
  20. void method1() {
  21. // 做一些事情
  22. context.changeState(AnotherConcreteState);
  23. }
  24. void method2() {
  25. // 做一些其他事情
  26. context.changeState(YetAnotherConcreteState);
  27. }
  28. void enter() { /* 做一些事情 */ }
  29. void exit() { /* 做一些事情 */ }
  30. }
英文:

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:

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. }
  6. void changeState(next) {
  7. state.exit();
  8. this.state = next;
  9. state.enter();
  10. }
  11. }
  12. abstract class State {
  13. Context context;
  14. // other methods
  15. }
  16. class ConcreteState extends State {
  17. void method1() {
  18. // do something
  19. context.changeState(AnotherConcreteState);
  20. }
  21. void enter() { /* do something */ }
  22. void exit() { /* do something */ }
  23. }

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

  1. class Context {
  2. State state;
  3. void method1() {
  4. state.method1();
  5. }
  6. void method2() {
  7. state.method2();
  8. }
  9. void changeState(next) {
  10. state.exit();
  11. this.state = next;
  12. state.enter();
  13. }
  14. }
  15. abstract class State {
  16. Context context;
  17. // other methods
  18. }
  19. class ConcreteState extends State {
  20. void method1() {
  21. // do something
  22. context.changeState(AnotherConcreteState);
  23. }
  24. void method2() {
  25. // do something else
  26. context.changeState(YetAnotherConcreteState);
  27. }
  28. void enter() { /* do something */ }
  29. void exit() { /* do something */ }
  30. }

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:

确定