實際開發中訂單往往都包含著訂單狀態,用戶每進行一次操作都要切換對應的狀態,而每次切換判斷當前的狀態是必須的,就不可避免的引入一系列判斷陳述句,為了讓代碼更加清晰直觀,我們引入今天的主角——狀態模式,
一、概念理解
假設訂單狀態有,下單、發貨、確認識訓,如果用戶確認識訓,在常規編程中就要判斷當前用戶的狀態,然后再修改狀態,如果這種情況下使用狀態模式,
將各個狀態都抽象成一個狀態類,比如下單狀態類、發貨狀態類、確認識訓類,在狀態類中處理相應的邏輯和控制下一個狀態,在定義一個環境類,定義初始狀態,并控制切換狀態,
在狀態模式中應該包含著三個角色:
環境類(Context)角色:也稱為背景關系,它定義了客戶端需要的介面,內部維護一個當前狀態,這個類持有State介面,負責保持并切換當前的狀態,
抽象狀態(State)角色:定義一個介面,用以封裝環境物件中的特定狀態所對應的行為,可以有一個或多個行為,
具體狀態(Concrete State)角色:實作抽象狀態所對應的行為,并且在需要的情況下進行狀態切換,
以下為狀態模式的類圖,看起來是很直觀的,理解起來也簡單,我們需要說明的是狀態模式的類圖和策略模式的類圖長的一樣,但寫起來狀態模式比策略模式要難,

我們要注意這段話,在狀態模式中,類的行為是基于它的狀態改變的,狀態之間的切換,在狀態A執行完畢后自己控制狀態指向狀態B,狀態模式是不停的切換狀態執行,這也是狀態模式和策略模式不一樣的地方,
另外在狀態模式中,狀態A到B是由自己控制的,而不是由客戶端來控制,這是狀態模式和策略模式最顯著的特征,
我們基于訂單狀態案例實作demo,
二、案例實作
抽象狀態:
定義統一的狀態切換方法
/**
* 抽象狀態
* @author tcy
* @Date 20-09-2022
*/
public abstract class OrderStateAbstract {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
/**
* 狀態切換
*/
public abstract void handle();
}
具體狀態-訂單付款:
實作狀態介面,處理相應的邏輯,并定義下一個狀態
/**
* 訂單付款
* @author tcy
* @Date 21-09-2022
*/
public class OrderStatePay extends OrderStateAbstract {
@Override
public void handle() {
System.out.println("訂單已支付,執行下個狀態...");
context.changeState(new OrderStateOut());
}
}
具體狀態-訂單發貨
/**
* 訂單發貨
* @author tcy
* @Date 21-09-2022
*/
public class OrderStateOut extends OrderStateAbstract {
@Override
public void handle() {
System.out.println("訂單已經發貨,開始下一狀態...");
context.changeState(new OrderStateSubmit());
}
}
具體狀態-訂單確認識訓
/**
* 訂單提交
* @author tcy
* @Date 21-09-2022
*/
public class OrderStateSubmit extends OrderStateAbstract {
@Override
public void handle() {
System.out.println("訂單已經確認識訓...");
}
}
環境類:
持有最新狀態,并呼叫具體的狀態切換方法
/**
* 環境類
* @author tcy
* @Date 20-09-2022
*/
public class Context {
private OrderStateAbstract state;
//定義環境類的初始狀態
public Context() {
this.state = new OrderStatePay();
state.setContext(this);
}
//狀態切換
public void changeState(OrderStateAbstract state) {
this.state = state;
this.state.setContext(this);
}
/**
* 審批通過請求
*/
public void request() {
this.state.handle();
}
}
客戶端呼叫:
/**
* @author tcy
* @Date 20-09-2022
*/
public class Client {
public static void main(String[] args) {
//創建環境
Context context = new Context();
//訂單付款
context.request();
//訂單發貨
context.request();
//訂單付款
context.request();
}
}
狀態模式客戶端呼叫比較簡單,由狀態內部類進行狀態切換,
三、總結
很多博客都將策略模式的案例代碼當做狀態模式來講解,這是不正確的,讀者可以參考策略模式兩篇做對比學習,認真體會他們之間的區別,
在實際開發中,當控制一個物件狀態轉換的條件運算式過于復雜時,就可以使用狀態模式把相關“判斷邏輯”提取出來,用各個不同的類進行表示,
系統處于哪種情況,直接使用相應的狀態類物件進行處理,這樣能把原來復雜的邏輯判斷簡單化,消除了 if-else、switch-case 等冗余陳述句,代碼更有層次性,并且具備良好的擴展力,
比如審批流程,我們案例也僅僅是用于訂單流程做例子,在實際開發中并不會使用這種方式處理訂單,因為訂單的處理邏輯實際上并不是那么復雜,引入狀態模式反而增加了更多的類,造成系統更加的復雜,這也是設計模式最顯著的缺點,
設計模式的學習要成體系,推薦你看我往期發布的設計模式文章,
一、設計模式概述
二、設計模式之工廠方法和抽象工廠
三、設計模式之單例和原型
四、設計模式之建造者模式
五、設計模式之代理模式
六、設計模式之配接器模式
七、設計模式之橋接模式
八、設計模式之組合模式
九、設計模式之裝飾器模式
十、設計模式之外觀模式
十一、外觀模式之享元模式
十二、設計模式之責任鏈模式
十三、設計模式之命令模式
十四、設計模式之解釋器模式
十五、設計模式之迭代器模式
十六、設計模式之中介者模式
十七、設計模式之備忘錄模式
十八、設計模式之觀察者模式
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509717.html
標籤:其他
上一篇:初識設計模式 - 橋接模式
