- 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(); } }
- 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("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結構圖如下: