十一大行爲型模式之八:狀態模式。java
姓名 :狀態模式
英文名 :State Pattern
價值觀 :有啥事讓狀態我來維護
我的介紹 :
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
當一個對象內在狀態改變時容許其改變行爲,這個對象看起來像改變了其類。
(來自《設計模式之禪》)設計模式
如今有好多我的貸款軟件,好比:支付寶、360借條(打廣告。。。)等等。貸款會有一個用戶狀態流程,遊客->註冊用戶->授信用戶->借款用戶(這裏簡化了狀態,只用 4 個)。每一個狀態擁有的權限不同,以下圖所示。app
從上圖能夠看到,一個用戶有 3 種行爲,分別是註冊、授信、借款。當註冊成功後,用戶的狀態就從『遊客』改變爲『註冊用戶』;當授信成功後,用戶的狀態就從『註冊用戶』改變爲『授信用戶』;當借款成功後,用戶的狀態就從『授信用戶』改變爲『借款用戶』。如今咱們就來實現用戶註冊、授信、借款的過程,由於每一個狀態的權限不同,因此這裏須要根據用戶的狀態來限制用戶行爲。ide
很快,咱們就完成下面的代碼。學習
class User { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public void register() { if ("none".equals(state)) { System.out.println("遊客。註冊中。。。"); }else if ("register".equals(state)) { System.out.println("註冊用戶。不須要再註冊。"); } else if ("apply".equals(state)) { System.out.println("授信用戶。不須要再註冊。"); } else if ("draw".equals(state)) { System.out.println("借款用戶。不須要再註冊。"); } } public void apply() { if ("none".equals(state)) { System.out.println("遊客。不能申請授信。"); }else if ("register".equals(state)) { System.out.println("註冊用戶。授信申請中。。。"); } else if ("apply".equals(state)) { System.out.println("授信用戶。不須要再授信。"); } else if ("draw".equals(state)) { System.out.println("借款用戶。不須要再授信。"); } } public void draw(double money) { if ("none".equals(state)) { System.out.println("遊客。申請借款【" + money + "】元。不能申請借款。"); } else if ("register".equals(state)) { System.out.println("註冊用戶。申請借款【" + money + "】元。還沒授信,不能借款。"); } else if ("apply".equals(state)) { System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。"); } else if ("draw".equals(state)) { System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。"); } } } public class NoStateTest { public static void main(String[] args) { User user = new User(); user.setState("register"); user.draw(1000); } } 打印結果: 註冊用戶。申請借款【1000.0】元。還沒授信,不能借款。
上面代碼實現了用戶 register (註冊),apply (授信),draw (借款) 這 3 種行爲,每一個行爲都會根據狀態 state 來作權限控制。看起來有點繁瑣,擴展性不高,假設新增了一個狀態,那麼註冊、授信、借款這 3 種行爲的代碼都要修改。下面經過狀態模式
來解決這個問題。this
咱們把狀態
給抽出來,做爲一個接口,由於在每種狀態中均可能有註冊、授信、借款行爲,因此把這 3 個行爲做爲狀態
接口的方法,讓每一個狀態子類都實現相應的行爲控制。以下代碼所示。設計
interface State { void register(); void apply(); void draw(double money); } /** * 遊客 */ class NoneState implements State { @Override public void register() { System.out.println("遊客。註冊中。。。"); } @Override public void apply() { System.out.println("遊客。不能申請授信。"); } @Override public void draw(double money) { System.out.println("遊客。申請借款【" + money + "】元。不能申請借款。"); } } /** * 註冊狀態 */ class RegisterState implements State { @Override public void register() { System.out.println("註冊用戶。不須要再註冊。"); } @Override public void apply() { System.out.println("註冊用戶。授信申請中。。。"); } @Override public void draw(double money) { System.out.println("註冊用戶。申請借款【" + money + "】元。還沒授信,不能借款。"); } } /** * 授信狀態 */ class ApplyState implements State { @Override public void register() { System.out.println("授信用戶。不須要再註冊。"); } @Override public void apply() { System.out.println("授信用戶。不須要再授信。"); } @Override public void draw(double money) { System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。"); } } /** * 借款狀態 */ class DrawState implements State { @Override public void register() { System.out.println("借款用戶。不須要再註冊。"); } @Override public void apply() { System.out.println("借款用戶。不須要再授信。"); } @Override public void draw(double money) { System.out.println("申請借款【" + money + "】元。申請借款中。。。"); } } class User1 { private State state; public State getState() { return state; } public void setState(State state) { this.state = state; } public void register() { this.state.register(); } public void apply() { this.state.apply(); } public void draw(double money) { this.state.draw(money); } } public class StateTest { public static void main(String[] args) { User1 user1 = new User1(); user1.setState(new RegisterState()); user1.apply(); user1.draw(1000); user1.setState(new ApplyState()); user1.draw(2000); } } 打印結果: 註冊用戶。授信申請中。。。 註冊用戶。申請借款【1000.0】元。還沒授信,不能借款。 授信用戶。申請借款【2000.0】元。申請借款中。。。
看上面代碼,咱們抽象了 State
接口,4 種狀態分別用 NoneState
(遊客)、RegisterState
(註冊)、ApplyState
(授信)、DrawState
(借款) 表示。而每一個狀態都有 3 種行爲,它們各自對這些行爲進行權限控制。這樣子實現可讓權限邏輯分離開,分散到每一個狀態裏面去,若是之後要業務擴展,要新增狀態,那就很方便了,只須要再實現一個狀態類就能夠,不會影響到其餘代碼。這也是爲何《阿里巴巴 Java 開發手冊》裏面講的,當超過 3 層的 if-else
的邏輯判斷代碼,推薦用狀態模式來重構代碼。code
狀態模式
很好的減低了代碼的複雜性,從而提升了系統的可維護性。在業務開發中能夠嘗試使用,好比在迭代開發中,業務邏輯愈來愈複雜,從而不得不使用不少 if-else
語句來實現時,就能夠考慮一下是否是能夠用 狀態模式
來重構,特別是一些有狀態流程轉換方面的業務。看到這篇文章,想一想工做中是否是有些複雜的代碼能夠重構,趕忙行動起來。對象
推薦閱讀:接口
設計模式系列文章持續更新中,歡迎關注公衆號 LieBrother,一塊兒交流學習。