由简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off、 small fire、medium fire与large fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if..else或是switch流程来控制,例如:
程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State 模式,将这个例子的 UML 类别结构画出就如下所示:
![]()
再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰 写:
接下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子, 如果一个状态可能转换至三个以上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原 书是如何实现TCP连线之间的状态转换的。
State模式的UML结构图如下:
![]()
- State.java
- Main.java
- IState.java
- OffState
- SmallState.java
- 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("medium fire");
}
}
- 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结构图如下:

浙公网安备 33010602011771号