最近在為澳洲一家保險公司做web應用,在一個收集用戶地址信息的頁面中,我遇到了一個問題:
1.當用戶輸入正確的地址,通過驗證。
2.當用戶第一次輸入錯誤的地址,不通過。
3.當用戶第二次輸入,不論正確與否,都將通過。
4.當用戶通過后返回上一個頁面如果地址沒有修改,通過。
5.當用戶通過后返回上一個頁面,地址修改,但不正確,不通過
當面對這樣的需求的時候,我立馬有了解決方案,首先要有一個全局變量來保存他輸入的地址是否正確的boolean,然后還得有一個session里存放一個地址變量,來比較地址是否改變。
有了這兩個變量,我就可以在做驗證的時候來通過判斷這兩個變量的值來決定是否調用驗證方法。第一次驗證,和第二次驗證都可以實現,但是當我想要實現從下個頁面跳回上個頁面的時候,我的驗證邏輯完全失效了,很明顯簡單的if else和變量已經讓整個程序變得臃腫不堪,邏輯混亂。但經過仔細分析之后,我們可以把用戶驗證的狀態分為:init, happy, retry, unhappy 四個狀態來判斷是否進行地址信息的驗證。如下圖所示:
通過分析得出四種狀態根據isHappyPath來決定自己狀態的變化,以及決定頁面的跳轉。
由此可抽象出狀態類:
public abstract class State { public abstract void changeState(boolean isHappyPath, StateContext stateContext); } public class HappyPath extends State { @Override public void changeState(boolean isHappyPath, StateContext stateContext) { if(!isHappyPath){
errors.reject("address is wrong"); stateContext.setState(new Retry()); } } } public class Retry extends State { @Override public void changeState(boolean isHappyPath, StateContext stateContext){ if(isHappyPath){ stateContext.setState(new HappyPath()); } else { stateContext.setState(new UnhappyPath());
} } } public class UnhappyPath extends State{ @Override public void changeState(boolean isHappyPath, StateContext stateContext){ if(isHappyPath) { stateContext.setState(new HappyPath()); } else if(stateContext.isAddressChanged()){
errors.reject("address is wrong"); stateContext.setState(new Retry()); } } }
在設計好狀態類和如何切換狀態之后,狀態機container的具體實現如下:
public class StateContext { private State state = new Init(); public void setState(State state) { this.state = state; } public void changeState(Address address) { state.changeState(isHappyPath(address), this); } public boolean isHappyPath(Address address){ return addressValidator(address); } }
如此簡單的幾個類就構成了狀態機的實現,方便處理了邏輯的轉化以及頁面跳轉的規則。State模式在實際使用中比較多,適合"狀態的切換".因為我們經常會使用If elseif else 進行狀態切換, 如果針對狀態的這樣判斷切換反復出現,我們就要聯想到是否可以采取State模式了.
希望能對大家有幫助。