狀態模式(State Pattern),當一個對象內在狀態改變
時容許其改變行爲
,這個對象看起來像改變了其類。簡而言之,就是狀態的變動引發了行爲的變動
。數據庫
下圖四輛汽車,分別表明汽車平常的四種狀態。
開門狀態:
this
關門狀態:
設計
飛奔狀態:
3d
中止狀態:
code
其中,某種特定狀態下,都有四個可執行操做,分別是open,close,run,stop,而後作對應的處理得下圖所示。
對象
類圖以下:
blog
CarState
,持有類型爲Context
的屬性,同時持有四個可執行操做,open
,close
,run
,stop
方法;OpenningState
,ClosingState
,RunningState
,StoppingState
,分別表明開門狀態,關門狀態,飛奔狀態,中止狀態;Context
,把狀態對象聲明爲靜態常量,有幾個狀態對象就聲明幾個靜態常量,環境角色具備狀態抽象角色定義的全部行爲,具體執行使用委託方式。具體環境角色有兩個職責:處理本狀態必須完成的任務,決定是否能夠過渡到其餘狀態。代碼實現以下:get
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 20:10 * @Desc: 汽車狀態抽象類 */ public abstract class CarState { //環境角色,封裝狀態變化引發的行爲變化 protected Context context; public void setContext(Context context) { this.context = context; } //汽車開門動做 public abstract void open(); //汽車關門動做 public abstract void close(); //汽車飛奔動做 public abstract void run(); //汽車中止動做 public abstract void stop(); }
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 20:23 * @Desc: 汽車開門狀態類 */ public class OpenningState extends CarState { //打開汽車門 public void open() { System.out.println("汽車門已開"); } //關閉汽車門 public void close() { //狀態修改 super.context.setCarState(Context.closingState); //動做委託爲ClosingState來執行 super.context.getCarState().close(); } //門開着時汽車通常不奔跑 public void run() { System.out.println("汽車開門狀態,不能奔跑"); } //車門開着時,切換不到中止狀態,由於沒有四種狀態中,沒有開門且中止這個狀態 public void stop() { System.out.println("汽車開門狀態,不能長時間開着門且處於中止狀態"); } }
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 20:23 * @Desc: 汽車飛奔狀態類 */ public class RunningState extends CarState { //打開奔跑時不開門 public void open() { System.out.println("車在飛奔,不能打開"); } //奔跑時確定是關門的 public void close() { System.out.println("車在飛奔,已經關閉,不能再次關閉"); } //汽車在飛奔 public void run() { System.out.println("汽車在飛奔"); } //汽車能夠停下來 public void stop() { //修改汽車爲中止狀態 super.context.setCarState(Context.stoppingState); //中止動做委託爲StoppingState類來執行 super.context.getCarState().stop(); } }
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 20:23 * @Desc: 汽車關門狀態類 */ public class ClosingState extends CarState { //打開汽車門 public void open() { //修改汽車爲開門狀態 super.context.setCarState(Context.openningState); //動做委託爲OpenningState類來執行 super.context.getCarState().open(); } //關閉汽車門 public void close() { System.out.println("汽車門已關"); } //汽車在飛奔 public void run() { //修改汽車爲飛奔狀態 super.context.setCarState(Context.runningState); //動做委託爲RunningState類來執行 super.context.getCarState().run(); } //汽車在中止 public void stop() { //設置汽車狀態爲中止狀態 super.context.setCarState(Context.stoppingState); //動做委託爲StoppingState類來執行 super.context.getCarState().stop(); } }
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 20:19 * @Desc: 上下文環境類 */ public class Context { /**列出汽車全部狀態 * openningState-開門狀態 closingState-關門狀態 * runningState-奔馳狀態 stoppingState-中止狀態 */ public static final OpenningState openningState = new OpenningState(); public static final ClosingState closingState = new ClosingState(); public static final RunningState runningState = new RunningState(); public static final StoppingState stoppingState = new StoppingState(); //定義汽車當前狀態 private CarState carState; public CarState getCarState() { return carState; } public void setCarState(CarState carState) { this.carState = carState; //切換狀態 this.carState.setContext(this); } //汽車開門 public void open() { this.carState.open(); } //汽車關門 public void close(){ this.carState.close(); } //汽車飛奔 public void run(){ this.carState.run(); } //汽車中止 public void stop(){ this.carState.stop(); } }
客戶端類以下:it
package com.wzj.state.example1; /** * @Author: wzj * @Date: 2019/11/3 21:06 * @Desc: */ public class Client { public static void main(String[] args) { Context context = new Context(); context.setCarState(new OpenningState()); // context.setCarState(new ClosingState()); // context.setCarState(new RunningState()); // context.setCarState(new StoppingState()); context.open(); // context.close(); // context.run(); // context.stop(); } }
執行結果以下:
當只打開Client
15行的時候,分別打開11,12,13,14行的代碼,會獲得以下結果:
汽車爲開門狀態時,執行open
class
汽車爲關門狀態時,執行open
汽車爲飛奔狀態時,執行open
汽車爲中止狀態時,執行open
上述結果能夠看出,一樣執行一個open
方法,當狀態的變化時致使行爲的變化。
優勢