Java 具有不同实现的状态模式导致难以理解的错误
Java State Pattern with different implementation resulting in a difficult to understand error
为什么这个 java 代码不起作用。
abstract class Actor {
Actor a = new HappyActor();
abstract void act();
void change() { a = new SadActor(); }
void go() { a.act(); }
}
class HappyActor extends Actor {
public void act() {
System.out.println( ":)" );
}
}
class SadActor extends Actor {
public void act() {
System.out.println( ":(" );
}
}
public class TransmogrifyMe {
public static void main( String[] args ) {
Actor s = new HappyActor();
s.go(); // Prints ":)"
s.change();
s.go(); // Prints ":("
}
}
这是我对流行的状态模式的修改,但不幸的是没有用:
抽象 class 中的赋值语句在每个继承它的 class 构造函数的开头调用。所以赋值语句试图创建一个派生的对象class。即 Actor a = new HappyActor()
在 class HappyActor
的构造函数被调用时被调用,这导致构造函数调用永无止境的循环。真的是这样吗?
工作版本类似于下面的代码:
abstract class Actor {
abstract void act();
}
class HappyActor extends Actor {
public void act() {
System.out.println( ":)" );
}
}
class SadActor extends Actor {
public void act() {
System.out.println( ":(" );
}
}
class Stage {
Actor a = new HappyActor();
void change() { a = new SadActor(); }
void go() { a.act(); }
}
public class Transmogrify {
public static void main( String[] args ) {
Stage s = new Stage();
s.go(); // Prints ":)"
s.change();
s.go(); // Prints ":("
}
}
第一个代码中产生的错误消息是这两行的无限循环:
at Actor.<init>(TransmogrifyMe.java:6)
at HappyActor.<init>(TransmogrifyMe.java:12)
是否可以使用继承来实现这种状态变化。我在 Bruce Eckel 的书中找到了这个 Thinking in Java In contrast you can't decide to inherit 运行 时间不同;必须在编译时完全确定
想一想当您尝试创建第一个 HappyActor
时会发生什么。默认的 ctor 需要首先创建 Actor
的核心,而要做的第一件事就是尝试构建 HappyActor
。繁荣,无限递归。
在第二个代码示例中,确实正确,Actor是Stage的"State"。 (也许 Actor 如此独立且独立于 Stage,更像是一种 Strategy,但在这种复杂程度下,差异是没有意义的。)
你还想做点别的吗?
删除 class 变量。您的方法应如下所示:
State doSomething() {
// do something, e.g. println.
return new NextState();
// or return this to stay in the current state.
}
然后像这样使用它们:
state = state.doSomething();
即你 return
下一个 状态。
例如
class HappyState implements State {
public State change() {
return new SadState();
}
}
于是我就按照Anony-Mousse的建议这样做了:
// StateChange.java
// Implementing the state pattern using inheritance
interface State {
public State change();
public void print();
}
class SadState implements State {
public State change() {
return new SadState();
}
public void print() {
System.out.println( ":(" );
}
}
class HappyState implements State {
public State change() {
return new SadState();
}
public void print() {
System.out.println( ":)" );
}
}
public class StateChange {
public static void main( String[] args ) {
State h = new HappyState();
h.print(); // prints :)
h = h.change();
h.print(); // prints :(
h = h.change();
h.print(); // prints :)
}
}
我已经尽力了!
为什么这个 java 代码不起作用。
abstract class Actor {
Actor a = new HappyActor();
abstract void act();
void change() { a = new SadActor(); }
void go() { a.act(); }
}
class HappyActor extends Actor {
public void act() {
System.out.println( ":)" );
}
}
class SadActor extends Actor {
public void act() {
System.out.println( ":(" );
}
}
public class TransmogrifyMe {
public static void main( String[] args ) {
Actor s = new HappyActor();
s.go(); // Prints ":)"
s.change();
s.go(); // Prints ":("
}
}
这是我对流行的状态模式的修改,但不幸的是没有用:
抽象 class 中的赋值语句在每个继承它的 class 构造函数的开头调用。所以赋值语句试图创建一个派生的对象class。即 Actor a = new HappyActor()
在 class HappyActor
的构造函数被调用时被调用,这导致构造函数调用永无止境的循环。真的是这样吗?
工作版本类似于下面的代码:
abstract class Actor {
abstract void act();
}
class HappyActor extends Actor {
public void act() {
System.out.println( ":)" );
}
}
class SadActor extends Actor {
public void act() {
System.out.println( ":(" );
}
}
class Stage {
Actor a = new HappyActor();
void change() { a = new SadActor(); }
void go() { a.act(); }
}
public class Transmogrify {
public static void main( String[] args ) {
Stage s = new Stage();
s.go(); // Prints ":)"
s.change();
s.go(); // Prints ":("
}
}
第一个代码中产生的错误消息是这两行的无限循环:
at Actor.<init>(TransmogrifyMe.java:6)
at HappyActor.<init>(TransmogrifyMe.java:12)
是否可以使用继承来实现这种状态变化。我在 Bruce Eckel 的书中找到了这个 Thinking in Java In contrast you can't decide to inherit 运行 时间不同;必须在编译时完全确定
想一想当您尝试创建第一个 HappyActor
时会发生什么。默认的 ctor 需要首先创建 Actor
的核心,而要做的第一件事就是尝试构建 HappyActor
。繁荣,无限递归。
在第二个代码示例中,确实正确,Actor是Stage的"State"。 (也许 Actor 如此独立且独立于 Stage,更像是一种 Strategy,但在这种复杂程度下,差异是没有意义的。)
你还想做点别的吗?
删除 class 变量。您的方法应如下所示:
State doSomething() {
// do something, e.g. println.
return new NextState();
// or return this to stay in the current state.
}
然后像这样使用它们:
state = state.doSomething();
即你 return
下一个 状态。
例如
class HappyState implements State {
public State change() {
return new SadState();
}
}
于是我就按照Anony-Mousse的建议这样做了:
// StateChange.java
// Implementing the state pattern using inheritance
interface State {
public State change();
public void print();
}
class SadState implements State {
public State change() {
return new SadState();
}
public void print() {
System.out.println( ":(" );
}
}
class HappyState implements State {
public State change() {
return new SadState();
}
public void print() {
System.out.println( ":)" );
}
}
public class StateChange {
public static void main( String[] args ) {
State h = new HappyState();
h.print(); // prints :)
h = h.change();
h.print(); // prints :(
h = h.change();
h.print(); // prints :)
}
}
我已经尽力了!