狀態(tài)模式主要解決的是當(dāng)控制一個(gè)對(duì)象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過于復(fù)雜時(shí)的情況。把狀態(tài)判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類當(dāng)中,可以把復(fù)雜的判斷邏輯簡化。
結(jié)構(gòu)
- Context環(huán)境類
環(huán)境類中維護(hù)一個(gè)State對(duì)象,它是定義了當(dāng)前的狀態(tài)。 - State抽象狀態(tài)類
-
ConcreteState具體狀態(tài)類
每一個(gè)類封裝了一個(gè)狀態(tài)對(duì)應(yīng)的行為。
狀態(tài)模式
場景
酒店系統(tǒng)中,房間的狀態(tài)變化

簡單實(shí)現(xiàn)
package state;
public abstract class RoomState {
protected RoomContext room;
public abstract void reservation(); // 預(yù)定
public abstract void cancel(); // 退訂
public abstract void checkIn(); // 入住
public abstract void checkOut(); // 退房
}
package state;
public class FreeState extends RoomState {
public FreeState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("提供手機(jī)號(hào),預(yù)定成功");
room.setState(room.bookedState);
}
public void cancel() {
System.out.println("房間空閑,無需操作");
}
public void checkIn() {
System.out.println("提供身份證,成功入住");
room.setState(room.checkedInState);
}
public void checkOut() {
System.out.println("房間空閑,無需操作");
}
}
package state;
public class BookedState extends RoomState {
public BookedState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("房間已被預(yù)定,不接受其它預(yù)定,無需操作");
}
public void cancel() {
System.out.println("提供手機(jī)號(hào),退訂成功");
room.setState(room.freeState);
}
public void checkIn() {
System.out.println("提供手機(jī)號(hào)和身份證,成功入住");
room.setState(room.checkedInState);
}
public void checkOut() {
System.out.println("房間尚未入住,無需操作");
}
}
package state;
public class CheckedInState extends RoomState {
public CheckedInState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("房間已經(jīng)入住,無需操作");
}
public void cancel() {
System.out.println("房間已經(jīng)入住,無需操作");
}
public void checkIn() {
System.out.println("房間已經(jīng)入住,無需操作");
}
public void checkOut() {
System.out.println("成功退房");
room.setState(room.freeState);
}
}
package state;
public class RoomContext {
private RoomState state;
RoomState freeState = new FreeState(this);
RoomState bookedState = new BookedState(this);
RoomState checkedInState = new CheckedInState(this);
public RoomContext() {
this.state = freeState;
}
public void setState(RoomState state) {
this.state = state;
}
public void reservation() {
state.reservation();
}
public void cancel() {
state.cancel();
}
public void checkIn() {
state.checkIn();
}
public void checkOut() {
state.checkOut();
}
}
package state;
public class Client {
public static void main(String[] args) {
RoomContext room = new RoomContext();
room.reservation();
room.checkIn();
room.checkIn();
room.cancel();
room.checkOut();
}
}
輸出:
提供手機(jī)號(hào),預(yù)定成功
提供手機(jī)號(hào)和身份證,成功入住
房間已經(jīng)入住,無需操作
房間已經(jīng)入住,無需操作
成功退房
開發(fā)中常見的場景
- 銀行系統(tǒng)中賬號(hào)狀態(tài)的管理
- OA系統(tǒng)中公文狀態(tài)的管理
- 酒店系統(tǒng)中,房間狀態(tài)的管理
- 線程對(duì)象各狀態(tài)之間的切換
好處
- 將與特定狀態(tài)相關(guān)的行為局部化,并且將不同的行為分割開來。
將特定狀態(tài)相關(guān)的行為都放入一個(gè)對(duì)象中,由于所有狀態(tài)相關(guān)的代碼都存在于某個(gè)ConcreteState中,所以通過定義新的子類可以很容易地增加新的狀態(tài)和轉(zhuǎn)換。 - 狀態(tài)模式通過把各種狀態(tài)轉(zhuǎn)移邏輯分布到State的子類之間,來減少相互的依賴。
什么時(shí)候考慮使用狀態(tài)模式
- 當(dāng)一個(gè)對(duì)象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時(shí)刻根據(jù)狀態(tài)改變它的行為時(shí),就可以考慮使用狀態(tài)模式了。
