現實生活中我們經常會碰到狀态改變的場景,面對不同的場景我們會做出不同的處理。比如:
電梯的運作
• 維修、正常、自動關門、自動開門、向上運作、向下運作、消防狀态
紅綠燈
• 紅燈、黃燈、綠燈
企業或政府系統
• 公文的審批狀态
– 報帳單據審批狀态
– 假條審批
網上購物時,訂單的狀态
• 下單
• 已付款
• 已發貨
• 送貨中
• 已收貨
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICMyYTMvw1dvwlMvwlM3VWaWV2Zh1Wa-cmbw5CO3RTbiFjb2QTcvwFO0MTOxkDNtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
狀态模式
使用場景
本案例我們通過飯店入住的情況來示範,飯店房間的狀态有這麼幾個:已預訂,已入住,空閑。如果不用狀态模式我們的實作如下:
if(state=="空閑"){
if(預訂房間){
預定操作;
state="已預訂";
}else if(住進房間){
入住操作;
state="已入住";
}
}else if(“已預訂"){
if(住進房間){
入住操作;
state="已入住";
}else if(取消預訂){
取消操作;
state="空閑";
}
}
複制
這種實作中if語句過多,不便于維護修改。這時我們可以考慮用狀态模式來實作。
狀态模式實作
類圖結構
核心:
用于解決系統中複雜對象的狀态轉換以及不同狀态下行為的封裝問題
角色 | 說明 |
---|---|
Context環境類 | 環境類中維護一個State對象,他是定義了目前的狀态。 |
State | 具體狀态類 |
ConcreteState具體狀态類 | 每一個類封裝了一個狀态對應的行為 |
實作代碼
State
/**
* State 接口
* @author 波波烤鴨
* @email [email protected]
*
*/
public interface State {
void handle();
}
複制
State實作類
/**
* 已預訂狀态
* @author 波波烤鴨
* @email [email protected]
*
*/
public class BookedState implements State {
@Override
public void handle() {
System.out.println("房間已預訂!别人不能定!");
}
}
複制
/**
* 已入住狀态
* @author 波波烤鴨
* @email [email protected]
*
*/
public class CheckedInState implements State {
@Override
public void handle() {
System.out.println("房間已入住!請勿打擾!");
}
}
複制
/**
* 空閑狀态
* @author 波波烤鴨
* @email [email protected]
*
*/
public class FreeState implements State {
@Override
public void handle() {
System.out.println("房間空閑!!!沒人住!");
}
}
複制
房間對象
/**
* 房間對象
* @author 波波烤鴨
* @email [email protected]
*
*/
public class HomeContext {
//如果是銀行系統,這個Context類就是賬号。根據金額不同,切換不同的狀态!
private State state;
public void setState(State s){
System.out.println("修改狀态!");
state = s;
state.handle();
}
}
複制
client
public class Client {
public static void main(String[] args) {
// 擷取房間對象
HomeContext ctx = new HomeContext();
// 設定房間狀态
ctx.setState(new FreeState());
ctx.setState(new BookedState());
}
}
複制
輸出結果
修改狀态!
房間空閑!!!沒人住!
修改狀态!
房間已預訂!别人不能定!
複制
開發中常見的場景:
- 銀行系統中賬号狀态的管理
- OA系統中公文狀态的管理
- 酒店系統中,房間狀态的管理
- 線程對象各狀态之間的切換