文章目錄
-
- 什麼是狀态模式
- 設計與實作
-
- 初級方案
- 狀态模式
什麼是狀态模式
狀态模式是針對狀态機模型的程式設計套路,首先要知道狀态機是什麼。
狀态機是一種數學模型,用于對事物狀态的變化進行描述。不說那麼學術的概念了,用具體的例子來解釋會更容易了解。
電梯應該都知道吧,電梯工作過程可以簡化為幾種狀态:開門狀态、關門狀态、運作狀态、停止狀态。
- 開門狀态下可以關門
- 關門狀态下可以運作或者再次開門
- 運作狀态下可以停止
- 停止狀态下可以開門或者再次運作
用狀态圖表示就是:

在現實中,電梯停止後會自動開門,我這裡的狀态模型把“自動化”因素給剔除了,是以停止後的電梯還有可能進入運作狀态。
程式設計時如果遇到這樣的狀态機模型,就可以考慮使用狀态模式對其進行編碼。
設計與實作
初級方案
這裡先給出一個初級方案,也是通常情況下,大多數人最容易想到的方案。如果不感興趣,請直接去下一節看狀态模式的實作。
初級方案實作思路很簡單,就是熟練使用各種條件判斷。
代碼大概就像下面的樣子:
// 四種狀态枚舉
public enum StateEnum {
OPENING, CLOSING, RUNNING, STOPPING
}
// 電梯接口定義
public interface Elevator {
void setState(StateEnum state); // 設定目前狀态
void open(); // 開門指令
void close(); // 關門指令
void run(); // 運作指令
void stop(); // 停止指令
}
// 電梯接口實作
public class ElevatorImpl implements Elevator {
private StateEnum state;
@Override
public void setState(StateEnum state) {
this.state = state;
}
@Override
public void open() {
if (this.state == StateEnum.CLOSING || this.state == StateEnum.STOPPING) {
System.out.println("電梯開門");
this.setState(StateEnum.OPENING);
}
}
@Override
public void close() {
if (this.state == StateEnum.OPENING) {
System.out.println("電梯關門");
this.setState(StateEnum.CLOSING);
}
}
@Override
public void run() {
if (this.state == StateEnum.CLOSING || this.state == StateEnum.STOPPING) {
System.out.println("電梯運作");
this.setState(StateEnum.RUNNING);
}
}
@Override
public void stop() {
if (this.state == StateEnum.RUNNING) {
System.out.println("電梯停止");
this.setState(StateEnum.STOPPING);
}
}
}
// 測試方法
public static void main(String[] args) {
Elevator elevator = new ElevatorImpl();
elevator.setState(StateEnum.STOPPING);
elevator.open();
elevator.close();
elevator.run();
elevator.stop();
}
這樣的代碼容易想到,實作起來也很容易,但是有兩個明顯的缺點:
- 判斷條件太多,令人眼花缭亂,寫的時候容易出錯
- 如果有新增狀态,每個指令方法都得修改,違反開閉原則
狀态模式
初級方案是将電梯作為一個主體,狀态為其屬性,這樣封裝代碼符合人類的自然思維,必然也會導緻内部屬性狀态判斷較為繁雜。
狀态模式則是在初級方案的基礎上,将狀态從電梯屬性中拆分出來,作為獨立的主體。電梯隻提供工作指令的接口,指令實際執行過程則是委托給各個狀态主體。
來體會一下具體的代碼設計方案:
// 電梯狀态定義
public abstract class ElevatorState {
protected Elevator elevator;
public void setElevator(Elevator elevator) {
this.elevator = elevator;
}
public abstract void open();
public abstract void close();
public abstract void run();
public abstract void stop();
}
// 電梯接口
public interface Elevator {
ElevatorState getState(); // 擷取電梯狀态
void setState(ElevatorState state); // 設定電梯狀态
void open(); // 開門指令
void close(); // 關門指令
void run(); // 運作指令
void stop(); // 停止指令
}
// 開門狀态
public class OpeningState extends ElevatorState {
@Override
public void open() {
System.out.println("電梯開門");
}
@Override
public void close() {
super.elevator.setState(ElevatorImpl.CLOSING_STATE);
super.elevator.getState().close();
}
@Override
public void run() {}
@Override
public void stop() {}
}
// 關門狀态
public class ClosingState extends ElevatorState {
@Override
public void open() {
super.elevator.setState(ElevatorImpl.OPENING_STATE);
super.elevator.getState().open();
}
@Override
public void close() {
System.out.println("電梯關門");
}
@Override
public void run() {
super.elevator.setState(ElevatorImpl.RUNNING_STATE);
super.elevator.getState().run();
}
@Override
public void stop() {}
}
// 運作狀态
public class RunningState extends ElevatorState {
@Override
public void open() {}
@Override
public void close() {}
@Override
public void run() {
System.out.println("電梯運作");
}
@Override
public void stop() {
super.elevator.setState(ElevatorImpl.STOPPING_STATE);
super.elevator.getState().stop();
}
}
// 停止狀态
public class StoppingState extends ElevatorState {
@Override
public void open() {
super.elevator.setState(ElevatorImpl.OPENING_STATE);
super.elevator.getState().open();
}
@Override
public void close() {}
@Override
public void run() {
super.elevator.setState(ElevatorImpl.RUNNING_STATE);
super.elevator.getState().run();
}
@Override
public void stop() {
System.out.println("電梯停止");
}
}
// 電梯實作類
public class ElevatorImpl implements Elevator {
public final static OpeningState OPENING_STATE = new OpeningState();
public final static ClosingState CLOSING_STATE = new ClosingState();
public final static RunningState RUNNING_STATE = new RunningState();
public final static StoppingState STOPPING_STATE = new StoppingState();
private ElevatorState state;
@Override
public ElevatorState getState() {
return state;
}
@Override
public void setState(ElevatorState state) {
this.state = state;
this.state.setElevator(this);
}
@Override
public void open() {
this.state.open();
}
@Override
public void close() {
this.state.close();
}
@Override
public void run() {
this.state.run();
}
@Override
public void stop() {
this.state.stop();
}
}
// 測試方法
public static void main(String[] args) {
Elevator elevator = new ElevatorImpl();
elevator.setState(new ClosingState());
elevator.open();
elevator.close();
elevator.run();
elevator.stop();
}
看,類裡面的條件判斷語句都沒有了,新增狀态也很友善。
這就是狀态模式的作用,實作狀态機的運作過程,但是卻消除了各種條件判斷,很好的解耦了狀态之間的聯系。