設計模式-狀態模式
本片文章主要介紹狀態模式。
狀態模式:當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類。
狀態模式只要解決的是當控制一個物件狀態轉換的條件表示式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同的一系列類當中,可以把複雜的判斷邏輯化。當然,如果這個判斷很簡單,那就沒必要使用狀態模式。
我們先看下結構圖:
State類,抽象狀態類,定義一個介面與Context的一個特定狀態相關的行為。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:24 */ public interface State { void handle(Context context); }
ConcreteState類,集體狀態,每一個子類實現一個與Context的一個狀態相關的行為。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:27 */ public class ConcreteStateA implements State { @Override public void handle(Context context) { context.setState(new ConcreteStateB()); } }
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:27 */ public class ConcreteStateB implements State { @Override public void handle(Context context) { context.setState(new ConcreteStateA()); } }
Context類,維護一個ConcreteState子類的例項,這個例項定義當前的狀態。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:24 */ public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; System.out.println("當前狀態:" + state.getClass().getName()); } public void request() { state.handle(this); } }
然後是測試類和執行結果。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:29 */ public class Client { public static void main(String[] args) { Context context = new Context(new ConcreteStateA()); context.request(); context.request(); context.request(); context.request(); } }
可以看到我們沒呼叫一次request()方法就會改變一次狀態。
上面的例子很簡單,結構清晰但是理解起來卻很生硬,下面我們用大話設計模式一書中的工作狀態例子來展示一下。
我們還是先看下結構圖:
首先是抽象狀態類,定義一個抽象方法 “寫程式”。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 抽象狀態 * User: lwx * Date: 2019-04-08 * Time: 21:31 */ public interface WorkState { void writeProgram(Work work); }
上午和中午工作狀態類。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 上午工作狀態 * User: lwx * Date: 2019-04-08 * Time: 21:32 */ public class ForenoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 12) { System.out.println("當前時間:" + work.getHour() + "點 上午工作,精神百倍。"); } else { //超過12點,則轉入中午工作狀態 work.setWorkState(new NoonState()); work.writeProgram(); } } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 中午工作狀態 * User: lwx * Date: 2019-04-08 * Time: 21:39 */ public class NoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 13) { System.out.println("當前時間:" + work.getHour() + "點 餓了,午飯;犯困,午休。"); } else { //超過13點,轉入下午工作狀態 work.setWorkState(new AfternoonState()); work.writeProgram(); } } }
下午和傍晚工作狀態類。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 下午工作狀態 * User: lwx * Date: 2019-04-08 * Time: 21:43 */ public class AfternoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 17) { System.out.println("當前時間:" + work.getHour() + "點 下午狀態還不錯,繼續努力。"); } else { work.setWorkState(new EveningState()); work.writeProgram(); } } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 晚間工作狀態 * User: lwx * Date: 2019-04-08 * Time: 21:45 */ public class EveningState implements WorkState { @Override public void writeProgram(Work work) { if (work.getFinish() == null ? Boolean.FALSE : work.getFinish()) { //完成任務,轉入下班狀態 work.setWorkState(new RestState()); work.writeProgram(); } else { if (work.getHour() < 21) { System.out.println("當前時間:" + work.getHour() + "點 加班哦,疲勞至極。"); } else { //超過21點則轉入睡眠工作狀態 work.setWorkState(new SleepingState()); work.writeProgram(); } } } }
睡眠狀態和下班休息狀態類。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 睡眠狀態 * User: lwx * Date: 2019-04-08 * Time: 21:46 */ public class SleepingState implements WorkState { @Override public void writeProgram(Work work) { System.out.println("當前時間:" + work.getHour() + "點 不行了,睡著了。"); } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 下班休息狀態 * User: lwx * Date: 2019-04-08 * Time: 21:47 */ public class RestState implements WorkState { @Override public void writeProgram(Work work) { System.out.println("當前時間:" + work.getHour() + "點 下班回家了。"); } }
工作類。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:32 */ public class Work { private WorkState workState; // 鐘點 屬性,狀態轉化的依據 private Integer hour; // 任務完成 屬性,能下班的依據 private Boolean finish; public Work() { //工作初始化為上午工作狀態,即上午9點開始上班 this.workState = new ForenoonState(); } public void writeProgram() { workState.writeProgram(this); } public Boolean getFinish() { return finish; } public void setFinish(Boolean finish) { this.finish = finish; } public Integer getHour() { return hour; } public void setHour(Integer hour) { this.hour = hour; } public WorkState getWorkState() { return workState; } public void setWorkState(WorkState workState) { this.workState = workState; } }
最後是測試類和執行結果。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:54 */ public class WorkClient { public static void main(String[] args) { Work work = new Work(); work.setHour(9); work.writeProgram(); work.setHour(10); work.writeProgram(); work.setHour(12); work.writeProgram(); work.setHour(13); work.writeProgram(); work.setHour(14); work.writeProgram(); work.setHour(17); work.writeProgram(); work.setFinish(Boolean.TRUE); work.setHour(19); work.writeProgram(); work.setHour(22); work.writeProgram(); } }
狀態模式的優點:
1.將與特定狀態相關的行為區域性化,並且將不同狀態的行為分割化。
2.狀態模式通過把各種狀態轉移邏輯分佈到State的子類之間,來減少相互間的依賴。
最後附上demo的githup地址: https://github.com/yijinqincai/design_patterns
作者:一金芹菜
出處: https://www.cnblogs.com/yijinqincai/
本文版權歸作者,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。