狀態模式

狀態模式:當一個對象的內在狀態改變時改變其行爲,這個對象看起來像是改變了其類。

怎麼理解這句話呢,就是說利用狀態模式,我們將對象的每個狀態封裝爲各個類,那麼對象狀態的變化就是其各個狀態類之間的切換。
我的理解像除了用於多分枝情況外,更像是有限狀態機一樣,適用於業務邏輯是枚舉類型。

我們要實現一個接口,這個接口就是對象本來的有很多分支實現的功能

public interface State {
    void WriteProgram(Work work);
}

然後來看下對象:

public class Work {
    private State current;
    private double hour;
    private boolean finished = false;

    public Work() {
        current = new ForenoonState();
    }

    public void setHour(double h) {
        hour = h;
    }

    public double getHour() {
        return hour;
    }

    public void setCurrent(State s) {
        current = s;
    }

    public void writeProgram() {
        current.WriteProgram(this);
    }

    public boolean getTaskState() {
        return finished;
    }

    public void setTaskState(boolean f) {
        finished = f;
    }

}

通過setHour(double h)來變更狀態條件,current.WriteProgram(this)來調用每個狀態對應的方法,那麼對於Current狀態的切換是如何實現的呢?
最開始new work的時候,由於work的構造函數,所以work剛開始的狀態就是ForenoonState():

public class ForenoonState implements State {
    @Override
    public void WriteProgram(Work work) {
        if(work.getHour() < 12) {
            System.out.println("當前時間:" + work.getHour() + " 上午工作,精神百倍");
        }
        else {
            work.setCurrent(new NoonState());
            work.writeProgram();
        }
    }
}

看到沒有,在ForenoonState 判斷狀態條件,並且用work.setCurrent(new NoonState())更新work對象的狀態爲NoonState(),並調用下個狀態NoonState()狀態的方法writeProgram();
接下來都是一樣的思路,前一個狀態判斷應該走哪個分支:

public class NoonState implements State {
    @Override
    public void WriteProgram(Work work) {
        if(work.getHour() < 13) {
            System.out.println("當前時間:" + work.getHour() + " 餓了,午飯,犯困,午休。");
        }
        else {
            work.setCurrent(new AfternoonState());
            work.writeProgram();
        }

    }

}
public class AfternoonState implements State {
    @Override
    public void WriteProgram(Work work) {
        if(work.getHour() < 17) {
            System.out.println("當前時間:" + work.getHour() + " 下午狀態不錯,繼續努力!");
        }
        else {
            work.setCurrent(new EveningState());
            work.writeProgram();
        }
    }
}
public class EveningState implements State {
    @Override
    public void WriteProgram(Work work) {
        if(work.getTaskState()) {
            work.setCurrent(new RestState());
            work.writeProgram();
        }
        else {
            if(work.getHour() < 21) {
                System.out.println("當前時間:" + work.getHour() + " 加班哦,疲憊至極!");
            }
            else {
                work.setCurrent(new SleepingState());
                work.writeProgram();
            }
        }
    }
}
public class RestState implements State {
    @Override
    public void WriteProgram(Work work) {
        System.out.print("當前時間:" + work.getHour() + " 下班回家!!");
    }
}
public class SleepingState implements State {
    @Override
    public void WriteProgram(Work work) {
        System.out.println("當前時間:" + work.getHour() + " 不行了,睡着了");
    }
}

主函數代碼:

    Work emergencyProject = new Work();
    emergencyProject.setHour(9);
    emergencyProject.writeProgram();
    emergencyProject.setHour(10);
    emergencyProject.writeProgram();
    emergencyProject.setHour(12);
    emergencyProject.writeProgram();
    emergencyProject.setHour(13);
    emergencyProject.writeProgram();
    emergencyProject.setHour(14);
    emergencyProject.writeProgram();
    emergencyProject.setHour(17);
    emergencyProject.writeProgram();

    emergencyProject.setTaskState(false);

    emergencyProject.setHour(19);
    emergencyProject.writeProgram();
    emergencyProject.setHour(22);
    emergencyProject.writeProgram();

這種模式帶來的好處是,業務狀態作爲對象就不依賴於其他業務狀態了,如果需求變更,那麼我們只需要去修改相應裝態類。比如添加刪除一個分支,只需要增加刪除一個類並在前面狀態分支類中的判斷進行修改就行了。

我思考了下:甚至整個邏輯變化都沒事,因爲要實現的功能已經被你分割成一個個狀態;
邏輯的變化只是對這些狀態的重新組合罷了,相對修改起來就比較方便了。

對於對分支的應用場景我理解的是,對於同級的判斷狀態模式不好用,比如說:

if(1 == a) {
}
else if(2 == a) {
}
else if(3 == a) {
}

這種情況還不如放一個類裏判斷,既然同級,處理過程就不會有影響。

而對於往深度再判斷的,用狀態模式就比較好了:

if(1 == a) {
    if(1 == b) {
        if(1 == c) {
        }
    }
    else if(2 == b) {
        if(2 == c) {
        }
    }
}

你看,這樣就是從a=1狀態切到b=1或者2狀態再切到c對應狀態。只需要對每種狀態進行編程。這是我理解的狀態模式試用的場景。

發佈了27 篇原創文章 · 獲贊 2 · 訪問量 9668
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章