英文:
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
类。这里有一篇关于这个主题的好文章。请注意,类图中显示 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;
// 其他方法
}
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 */ }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论