狀態模式(State),當一個對象的內部狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。
狀態管理者架構
public class Context { //持有一個State類型的對象實例 private State state; public void setState(State state) { this.state = state; } /** * 客戶端調用 */ public void request(String sampleParameter) { //轉調state來處理 state.handle(sampleParameter); } }
抽象狀態ide
public interface State { /** * 狀態對應的處理 */ public void handle(String sampleParameter); }
具體狀態Athis
public class ConcreteStateA implements State { @Override public void handle(String sampleParameter) { System.out.println("ConcreteStateA handle :" + sampleParameter); } }
具體狀態Bspa
public class ConcreteStateB implements State { @Override public void handle(String sampleParameter) { System.out.println("ConcreteStateB handle :" + sampleParameter); } }
客戶端調用方
public class Client { public static void main(String[] args){ //建立狀態 State state = new ConcreteStateB(); //建立環境 Context context = new Context(); //將狀態設置到環境中 context.setState(state); //請求 context.request("test"); } }
小A正在召喚師峽谷廝殺,他玩的是卡特,買了一本殺人書。隨着遊戲時間的進行,小A殺的人愈來愈多,且本身都沒死過,遊戲中不斷傳來「XXX暴走了」、「XXX主宰了比賽」、「XXX接近神了」。最終小A以12殺0死的完美戰績結束了比賽,腦海中剛纔的捷報聲還在不停環繞在他的耳邊,他就想這不就是狀態模式,隨後打開IDE開始復現剛纔的過程。code
環境類orm
package com.jo.state; /** * @author Jo * @date 2018/1/17 */ public class LolContext { /** * 當前殺人狀態 */ private KillState killState; /** * 當前殺人數 */ private Integer killNum = 0; public LolContext() { killState = new Normal(); } public Integer getKillNum() { return killNum; } public LolContext setKillState(KillState killState) { this.killState = killState; return this; } /** * 殺人方法, */ public void kill(){ killNum += 1; killState.kill(this); System.out.println("當前擊殺數" + killNum); System.out.println(); } }
抽象殺人狀態對象
public interface KillState { /** * 抽象殺人方法 * @param lolContext */ void kill(LolContext lolContext); }
普通擊殺遊戲
public class Normal implements KillState { @Override public void kill(LolContext lolContext) { System.out.println("你殺了一我的"); //殺了2我的的時候轉換狀態 if (lolContext.getKillNum() > 1){ lolContext.setKillState(new KillingSpring()); } } }
大殺特殺圖片
public class KillingSpring implements KillState { @Override public void kill(LolContext lolContext) { System.out.println("你正在大殺特殺"); lolContext.setKillState(new Rampage()); } }
接近暴走get
public class Rampage implements KillState { @Override public void kill(LolContext lolContext) { System.out.println("你已經接近暴走了"); lolContext.setKillState(new Unstoppable()); } }
無人可擋
public class Unstoppable implements KillState { @Override public void kill(LolContext lolContext) { System.out.println("你已經無人可擋了"); lolContext.setKillState(new Dominating()); } }
、
、
、
、
超神
public class Legendary implements KillState { @Override public void kill(LolContext lolContext) { System.out.println("你已經超神了"); } }
客戶端調用
public class Client { public static void main(String[] args) { LolContext lolContext = new LolContext(); for (int i = 0; i < 13; i++) { lolContext.kill(); } } }
運行結果
客戶端只負責調用LolContext的kill方法,其他一律不知,內部便會隨着殺人數的增加打印不一樣的通知。而LolContext中也沒有複雜,一大串的if else switch case,狀態的轉移在各自的具體狀態中,若是須要修改部分邏輯只須要改對應的狀態,而不須要改本來在一塊兒的if else,大大減小了隱患的發生率,從而不會發生牽一髮而動全身的結果。
狀態模式的優勢是解除了程序的耦合度,採用子類的方式去除了煩瑣容易出錯的if else,但反而帶來的是類的數據增多。若是你要實現的功能狀態很少,且功能簡單,那不推薦使用狀態模式,否則會徒增程序的複雜性。且要執行的動做有必定的複雜度,此例的kill方法是最簡單的實現,實際應用中複雜度是遠遠大於它的。你能夠想象在狀態多,且複雜的動做中不使用狀態模式會事怎樣,if else多的眼花繚亂,上一個if和下一個else if相差幾百行代碼,想必這樣的代碼誰都不肯意碰,萬一改壞了就要背鍋了。
狀態模式和和策略模式有點相像,狀態模式的狀態轉移是內部控制的,而策略模式是由客戶端控制採用不一樣的策略。所以在目的和實現仍是有很大的差異的。有些場景「狀態」不是那麼明顯,須要轉換成狀態模式就考察使用者的功底和對業務的理解程度了,望你們都能get更多知識點,能力愈來愈強,個個都是架構師。