1、定義
(State)當一個對象的内在狀态改變時允許變其行為,這個對象看起來像是改變了其類。
2、使用場景
9點 上午工作 ,精神百倍
10點 上午工作,精神百倍
12點 餓了,午飯,犯困,午休
13點 下午狀态還不錯,繼續努力
14點 下午狀态還不錯,繼續努力
17點 加班額,疲勞至極
19點 加班額,疲勞至極
22點 不行了,睡着了
具體案例演變過程可參考書上
3、代碼結構UML圖

工作:維護一個ConcreteState子類的執行個體,這個執行個體定義目前狀态;
狀态:抽象狀态 類,定義一個接口以封裝與Context的一個特定狀态相關的行為;
上午、中午、下午、傍晚、下班、睡眠工作狀态:具體狀态類,每一個子類實作一個與Context的一個狀态相關的行為。
4、類的實作
(1)、State(抽象狀态)
public abstract class State {
public abstract void writeProgram(Work w);
}
(2)、ForenoonState(上午工作狀态類)
public class ForenoonState extends State{
@Override
public void writeProgram(Work w) {
if(w.getHour()<12){
System.out.println("目前時間:"+w.getHour()+"點 上午工作,精神百倍");
}else{
w.setState(new NoonState());
w.writeProgram();
}
}
}
(3)、NoonState(中午工作狀态類)
public class NoonState extends State{
@Override
public void writeProgram(Work w) {
if(w.getHour()<13){
System.out.println("目前時間:"+w.getHour()+"點 餓了,午飯;犯困,午休。");
}else{
w.setState(new AfternoonState());
w.writeProgram();
}
}
}
(4)、AfternoonState (下午工作狀态類)
public class AfternoonState extends State {
@Override
public void writeProgram(Work w) {
if(w.getHour()<17){
System.out.println("目前時間:"+w.getHour()+"點 下午狀态還不錯,繼續努力。");
}else{
w.setState(new EveningState());
w.writeProgram();
}
}
}
(5)、EveningState (傍晚工作狀态類)
public class EveningState extends State {
@Override
public void writeProgram(Work w) {
if(w.isFinish()){
w.setState(new RestState());
w.writeProgram();
}else{
if(w.getHour()<21){
System.out.println("目前時間:"+w.getHour()+"點 加班額,疲累至極。");
}else{
w.setState(new SleepingState());
w.writeProgram();
}
}
}
}
(6)、SleepingState (睡眠工作狀态類)
public class SleepingState extends State {
@Override
public void writeProgram(Work w) {
System.out.println("目前時間:"+w.getHour()+"點 不行了,睡着了。");
}
}
(7)、RestState(下班休息狀态類)
public class RestState extends State {
@Override
public void writeProgram(Work w) {
System.out.println("目前時間:"+w.getHour()+"點 下班回家了。");
}
}
5、用戶端調用
public static void main(String[] args) {
//緊急項目
Work emergencyProjects=new Work();
emergencyProjects.setHour(9);
emergencyProjects.writeProgram();
emergencyProjects.setHour(10);
emergencyProjects.writeProgram();
emergencyProjects.setHour(12);
emergencyProjects.writeProgram();
emergencyProjects.setHour(13);
emergencyProjects.writeProgram();
emergencyProjects.setHour(14);
emergencyProjects.writeProgram();
emergencyProjects.setHour(17);
emergencyProjects.writeProgram();
emergencyProjects.setFinish(false);
emergencyProjects.writeProgram();
emergencyProjects.setHour(19);
emergencyProjects.writeProgram();
emergencyProjects.setHour(22);
emergencyProjects.writeProgram();
}
輸出:
6、總結
狀态模式的好處是将與特定狀态相關的行為局部化,并将不同狀态的行為分割開來。
将特定狀态相關的行為都放入一個對象中,由于所有與狀态相關的代碼都存在于某個ConcreteState中,是以通過定義新的子類可以很容易地增加新的狀态和轉換。
狀态模式通過把各種狀态轉移邏輯分布到State的子類之間,來減少互相間的依賴。例如活字印刷術把版面改成了一個又一個的活字,此時就容易維護和擴充了。
當一個對象的行為取決于它的狀态,并且它必須在運作時刻根據狀态改變它的行為時,就可以考慮使用狀态模式了。
另外如果業務需求某項業務又多個狀态,通常都是一些枚舉常量,狀态的變化都是依靠大量的多分支判斷語句來實作,此時應該考慮将每一個業務狀态定義為一個State的子類。這樣這些對象就可以不依賴于其他對象而獨立變化了,某一天客戶需要更改需求,增加或減少業務狀态或改變狀态流程,對你來說都時不困難的事。
參考:《大話設計模式》