状态模式简单实现
工作過程中,我們經常遇到一些復雜的狀態轉換的問題,如果我們使用傳統的方式來處理狀態轉換,相信狀態上了10多個以上的時候,每個地方都是If else判斷測試的時候,你就知道痛苦了,在處理訂單狀態時候,10多個狀態也是常有的事情,我們可以借助狀態模式來解決這個問題,在多次項目過程中,使用該模式之后明顯感覺狀態處理要清晰得多,即使中間涉及到刪減或增加一些狀態?中間狀態,該模式處理起來游刃有余。
? 狀態轉換,絕大多數是由于事件觸發引起的,currentStatus___event___nextStatus,即在當前狀態下發生了一個事件促使狀態轉移到下一個狀態,設計模式中詳細進行了闡述,這里我只給一個簡單的實現。
public enum Status {
?? ?wait(1) {// 等待發送狀態
?? ???? @Override
?? ???? protected void initMap() {
?? ???? ??? addEventTansferMap(Event.send, sended);
?? ???? }
?? ?},
?? ?sended(2) {// 已經發送狀態
?? ???? @Override
?? ???? protected void initMap() {
?? ???? ??? addEventTansferMap(Event.confirm, confirmed);
?? ???? }
?? ?},
?? ?confirmed(3) {// 已經確認狀態
?? ???? @Override
?? ???? protected void initMap() {}
?? ?};
?? ?/***************************************************************************
?? ? *
?? ? * 共有方法
?? ? *
?? ? * *******************************************************************************
?? ? */
?? ?private Status(int value) {
?? ???? this.value = value;
?? ?}
?? ?
?? ?public int getValue(){
?? ???? return this.value;
?? ?}
?? ?protected abstract void initMap();// 初始化映射事件狀態映射關系
?? ?/**
?? ? * 根據發生的事件得到下一個狀態
?? ? *
?? ? * @param e
?? ? *??????????? 事件
?? ? * @return 下一個狀態,如果該事件沒有造成狀態改變,返回null
?? ? */
?? ?public final Status next(Event e) {
?? ???? init();
?? ???? return translations.get(e);
?? ?}
?? ?
?? ?/**
?? ? * 初始化事件與狀態轉換映射
?? ? */
?? ?private void init() {
?? ???? if (false == initialed) {// double checked
?? ???? ??? synchronized (LOCK) {
?? ???? ??? ??? if (false == initialed) {
?? ???? ??? ??? ??? translations = new EnumMap<Event, Status>(Event.class);
?? ???? ??? ??? ??? initMap();
?? ???? ??? ??? ??? initialed = true;
?? ???? ??? ??? }
?? ???? ??? }
?? ???? }
?? ?}
?? ?/**
?? ? *
?? ? * @param e 發生的事件
?? ? * @param s 事件發生后轉移到的狀態
?? ? */
?? ?protected void addEventTansferMap(Event e,Status s){
?? ???? translations.put(e, s);
?? ?}
?? ?private Map<Event, Status> translations;?? ?//事件狀態映射
?? ?private boolean initialed = false;?? ?// 映射是否已經初始化
?? ?private int value;?? ?//狀態原始值
?? ?private Object LOCK = new Object();
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?
?? ?// 事件枚舉,可以單獨作為一個類
?? ?public enum Event {
?? ???? send, // 發送事件
?? ???? confirm;// 確認事件
?? ?}
?? ?public static void main(String[] args) {
?? ???? System.out.println("下一個狀態:" + wait.next(Event.send));
?? ???? System.out.println(sended.next(Event.confirm));
?? ???? System.out.println(wait.next(Event.confirm));
?? ?}
}
?由以上實現可以知道,新增一個狀態,新增一個事件都非常簡單。第一步,在Event中新增一個事件,第二步,在Status中新增一個狀態 ,第三步,新增事件和狀態轉移映射(覆蓋initMap即可)。
在使用時只需要使用當前的發生的事件作為參數調用next即可以得到下一個狀態,非常簡單。
總結