如果您不了解TCP的连线方式,在看Gof的书介绍State 状态模式 时,大概会看得一头雾水吧! TCP的连线状态图,光是要了解就要花点精神了,它的连线状态很多,用来说明状态模式确实很适合,但不适合教导初学模式的人.
由 简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off, small fire,medium fire与large fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if...else...或是switch流程来控制,例如:
State.java
public class State {
private int state;
public State() {
state = 0;
}
public void switchFire() {
if (state == 0) {
state = 1; System.out.println( "small fire" );
} else if (state == 1) {
state = 2; System.out.println( "medium fire" );
} else if (state == 2) {
state = 3; System.out.println( "large fire" ); } else {
state = 0; System.out.println( "turning off" ); }
}
}
Main.java
public class Main {
public static void main(String[] args) {
State state = new State();
state.switchFire();
state.switchFire();
state.switchFire();
state.switchFire(); }
}
这 个方法很简单,每个人都会,但如果您的状态变化并不是流水式的变化,而是像TCP连线状态一样,会是一个网络图的时候,用if...else或 switch来写的话,您的程式就会乱的不像话了;来考虑如何让物件控制自己的状态转换与所应表现的行为,这个程式可以这样改写:
IState.java
public interface IState { public void switchFire(FireSwitch sw); }
OffState
public class OffState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new SmallState());
System.out.println( "small fire" ); }
}
SmallState.java
public class SmallState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new MediumState());
System.out.println( "medium fire" ); }
}
MediumState.java
public class MediumState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new LargeState());
System.out.println( "large fire" ); }
}
LargeState.java
public class LargeState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new OffState()); System.out.println( "off fire" ); }
}
FireSwitch.java
public class FireSwitch {
private State current;
public FireSwitch() { current = new OffState(); }
public void setState(State s) { current = s; }
public void switchFire() { current.switchFire(this); }
}
Main.java
public class Main {
public static void main(String[] args) {
FireSwitch fireSwitch = new FireSwitch();
fireSwitch.switchFire();
fireSwitch.switchFire();
fireSwitch.switchFire();
fireSwitch.switchFire(); }
}
程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State模式,将这个例子的UML类别结构画出就如下所示:
再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰写:
IState.java
public interface IState {
public void switchClockWise(FireSwitch sw);
public void switchCountClock(FireSwitch sw);
}
OffState.java
public class OffState implements IState { public void switchClockWise(FireSwitch sw) { sw.setState(new SmallState()); System.out.println("small fire"); } public void switchCountClock(FireSwitch sw) { sw.setState(new LargeState()); System.out.println("large fire"); } }
SmallState.java
public class SmallState implements IState {
public void switchClockWise(FireSwitch sw) { sw.setState(new MediumState()); System.out.println("medium fire"); }
public void switchCountClock(FireSwitch sw) { sw.setState(new OffState()); System.out.println("off fire"); }
}
MediumState.java
public class MediumState implements IState {
public void switchClockWise(FireSwitch sw) { sw.setState(new LargeState()); System.out.println("large fire"); } public void switchCountClock(FireSwitch sw) { sw.setState(new SmallState()); System.out.println("small fire"); }
}
LargeState.java
public class LargeState implements State {
public void switchClockWise(FireSwitch sw) { sw.setState(new OffState()); System.out.println("off fire"); }
public void switchCountClock(FireSwitch sw) { sw.setState(new MediumState()); System.out.println("mediumfire"); }
}
FireSwitch.java
public class FireSwitch {
private State current;
public FireSwitch() { current = new OffState(); }
public void setState(State s) { current = s; }
public void switchClockWise() { current.switchClockWise(this); }
public void switchCountClock() { current.switchCountClock(this); }
}
Main.java
public class Main {
public static void main(String[] args) {
FireSwitch fireSwitch = new FireSwitch();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
System.out .println();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock(); }
}
接 下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子,如果一个状态可能转换至三个以 上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原书是如何实现TCP连线之间的 状态转换的.
State模式的UML结构图如下:
由 简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off, small fire,medium fire与large fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if...else...或是switch流程来控制,例如:
State.java
public class State {
private int state;
public State() {
state = 0;
}
public void switchFire() {
if (state == 0) {
state = 1; System.out.println( "small fire" );
} else if (state == 1) {
state = 2; System.out.println( "medium fire" );
} else if (state == 2) {
state = 3; System.out.println( "large fire" ); } else {
state = 0; System.out.println( "turning off" ); }
}
}
Main.java
public class Main {
public static void main(String[] args) {
State state = new State();
state.switchFire();
state.switchFire();
state.switchFire();
state.switchFire(); }
}
这 个方法很简单,每个人都会,但如果您的状态变化并不是流水式的变化,而是像TCP连线状态一样,会是一个网络图的时候,用if...else或 switch来写的话,您的程式就会乱的不像话了;来考虑如何让物件控制自己的状态转换与所应表现的行为,这个程式可以这样改写:
IState.java
public interface IState { public void switchFire(FireSwitch sw); }
OffState
public class OffState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new SmallState());
System.out.println( "small fire" ); }
}
SmallState.java
public class SmallState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new MediumState());
System.out.println( "medium fire" ); }
}
MediumState.java
public class MediumState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new LargeState());
System.out.println( "large fire" ); }
}
LargeState.java
public class LargeState implements IState {
public void switchFire(FireSwitch sw) {
sw.setState(new OffState()); System.out.println( "off fire" ); }
}
FireSwitch.java
public class FireSwitch {
private State current;
public FireSwitch() { current = new OffState(); }
public void setState(State s) { current = s; }
public void switchFire() { current.switchFire(this); }
}
Main.java
public class Main {
public static void main(String[] args) {
FireSwitch fireSwitch = new FireSwitch();
fireSwitch.switchFire();
fireSwitch.switchFire();
fireSwitch.switchFire();
fireSwitch.switchFire(); }
}
程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State模式,将这个例子的UML类别结构画出就如下所示:

再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰写:
IState.java
public interface IState {
public void switchClockWise(FireSwitch sw);
public void switchCountClock(FireSwitch sw);
}
OffState.java
public class OffState implements IState { public void switchClockWise(FireSwitch sw) { sw.setState(new SmallState()); System.out.println("small fire"); } public void switchCountClock(FireSwitch sw) { sw.setState(new LargeState()); System.out.println("large fire"); } }
SmallState.java
public class SmallState implements IState {
public void switchClockWise(FireSwitch sw) { sw.setState(new MediumState()); System.out.println("medium fire"); }
public void switchCountClock(FireSwitch sw) { sw.setState(new OffState()); System.out.println("off fire"); }
}
MediumState.java
public class MediumState implements IState {
public void switchClockWise(FireSwitch sw) { sw.setState(new LargeState()); System.out.println("large fire"); } public void switchCountClock(FireSwitch sw) { sw.setState(new SmallState()); System.out.println("small fire"); }
}
LargeState.java
public class LargeState implements State {
public void switchClockWise(FireSwitch sw) { sw.setState(new OffState()); System.out.println("off fire"); }
public void switchCountClock(FireSwitch sw) { sw.setState(new MediumState()); System.out.println("mediumfire"); }
}
FireSwitch.java
public class FireSwitch {
private State current;
public FireSwitch() { current = new OffState(); }
public void setState(State s) { current = s; }
public void switchClockWise() { current.switchClockWise(this); }
public void switchCountClock() { current.switchCountClock(this); }
}
Main.java
public class Main {
public static void main(String[] args) {
FireSwitch fireSwitch = new FireSwitch();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
fireSwitch.switchClockWise();
System.out .println();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock();
fireSwitch.switchCountClock(); }
}
接 下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子,如果一个状态可能转换至三个以 上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原书是如何实现TCP连线之间的 状态转换的.
State模式的UML结构图如下:
