狀態模式
狀態模式,個人認為通過將對象行為包裝在不同狀態對象里面,通過控制狀態的變化來實現行為的差異。關于狀態模式的使用場景,如果一個對象在不同狀態(至少3個狀態)下有不同行為,而且還有增加狀態的趨勢,可以考慮使用狀態模式。拿電梯(來源于Java 設計模式——狀態模式)來說,眾所周知,電梯至少有四種狀態: 開門狀態,關門狀態,運行狀態,停止狀態。
下面用一張表將狀態和對應的動作列出來:

對應的狀態圖:

為了有所區別,每個狀態之間的聯系是不一樣的,如Closed狀態和其他狀態之間用虛線,而open狀態和closed狀態之前使用實線,可以看出,狀態圖和上面的表格是一致的。 下面再看看代碼實現:
public interface IElevator { void open(); void close(); void run(); void stop(); }
1 public class Elevator implements IElevator { 2 3 @Override 4 public void open() { 5 System.out.println("open the elevator"); 6 } 7 8 @Override 9 public void close() { 10 System.out.println("close the elevator"); 11 } 12 13 @Override 14 public void run() { 15 System.out.println("run the elevator"); 16 } 17 18 @Override 19 public void stop() { 20 System.out.println("stop the elevator"); 21 } 22 }
public class Context { /*package*/ final State openState = new OpenState(this); /*package*/ final State closedState = new ClosedState(this); /*package*/ final State runningState = new RunningState(this); /*package*/ final State stoppedState = new StoppedState(this); /*package*/ final IElevator elevator; private State state; public Context(IElevator elevator) { this.elevator = elevator; this.state = openState; } public IElevator getElevator() { return elevator; } public void setState(State state) { this.state = state; } public void open() { state.open(); } public void close() { state.close(); } public void run() { state.run(); } public void stop() { state.stop(); } public static void main(String[] param) { Context context = new Context(new Elevator()); context.close(); context.run(); context.open(); } }
public abstract class State implements IElevator { protected final Context context; public State(Context context) { this.context = context; } protected void log(String state, String action) { System.out.println("Elevator can't take action " + action + " in state " + state); } }
public class OpenState extends State { public OpenState(Context context) { super(context); } @Override public void open() { log("open", "open"); } @Override public void close() { context.getElevator().close(); context.setState(context.closedState); } @Override public void run() { log("open", "run"); } @Override public void stop() { log("open", "stop"); } }
public class ClosedState extends State { public ClosedState(Context context) { super(context); } @Override public void open() { context.getElevator().open(); context.setState(context.openState); } @Override public void close() { log("closed", "close"); } @Override public void run() { context.getElevator().run(); context.setState(context.runningState); } @Override public void stop() { context.getElevator().stop(); context.setState(context.stoppedState); } }
public class RunningState extends State { public RunningState(Context context) { super(context); } @Override public void open() { log("running", "open"); } @Override public void close() { log("running", "close"); } @Override public void run() { log("running", "run"); } @Override public void stop() { context.getElevator().stop(); } }
public class StoppedState extends State { public StoppedState(Context context) { super(context); } @Override public void open() { context.getElevator().open(); context.setState(context.openState); } @Override public void close() { log("stopped", "close"); } @Override public void run() { context.getElevator().run(); context.setState(context.runningState); } @Override public void stop() { log("stopped", "stop"); } }
代碼和簡單,類圖如下:

現在問題來了,新聞上經常報告電梯出事,上級要求每個電梯添加急救按鈕,用戶在緊急情況下可以按下此按鈕逃生。想想看,如果之前沒有使用狀態模式,拿到這個需求程序員是不是有想死的沖動 , 而狀態模式能很好解決這個需求只需要添加urgent動作就可以了。

如果各位還不過癮,我想再拿個打電話的小例子,狀態圖如下:

如果手機新增一個urgent功能:

具體代碼我就不展示了,具體代碼可以參見: https://github.com/breakJeff/designPattern,如果發現問題,請及時留言。
浙公網安備 33010602011771號