一、狀態模式實現方式
- 核心結構
- 狀態接口(State):定義狀態相關的行為方法。
- 具體狀態類(ConcreteState):實現狀態接口,封裝特定狀態下的邏輯。
- 上下文類(Context):維護當前狀態引用,委托請求給當前狀態對象處理。
- 基礎實現示例(以電梯控制為例)
// 狀態接口
public interface ElevatorState {void handle(ElevatorContext context);
}
// 具體狀態類:停止狀態
public class StopState implements ElevatorState {@Overridepublic void handle(ElevatorContext context) {System.out.println("電梯已停止");context.setState(new RunningState()); // 切換狀態}
}
// 上下文類
public class ElevatorContext {private ElevatorState state;public ElevatorContext(ElevatorState initialState) {this.state = initialState;}public void setState(ElevatorState state) {this.state = state;}public void request() {state.handle(this); // 委托處理}
}
- 高級實現技巧
- 狀態內部維護上下文:允許狀態類直接操作上下文屬性(如訂單狀態流轉)。
- 狀態工廠優化:集中管理狀態對象,避免重復創建。
- 狀態共享(單例模式):適用于無狀態對象(如紅綠燈狀態)。
二、測試方法與策略
- 測試目標
- 驗證狀態切換的正確性(如訂單從“待支付”到“已發貨”)。
- 確保每個狀態下的行為符合預期(如電梯停止時禁止移動)。
- 單元測試工具
使用Mockito框架模擬依賴對象,隔離測試環境:
import static org.mockito.Mockito.*;
// 測試訂單狀態切換
public class OrderTest {@Testpublic void testOrderStateTransition() {Order order = new Order();OrderState initialState = mock(NewState.class);order.setState(initialState);// 模擬支付操作觸發狀態切換order.pay();verify(initialState).next(order); // 驗證狀態轉換assertEquals(PaidState.class, order.getState().getClass());}
}
- 關鍵測試場景
- 狀態轉換驗證
使用verify()
檢查狀態切換方法是否按預期調用。verify(context, times(1)).setState(any(RunningState.class));
- 行為邏輯驗證
結合斷言(JUnit/Hamcrest)驗證輸出結果:assertThat(outputStream.toString(), containsString("電梯已停止"));
- 異常處理測試
模擬非法狀態操作(如未支付時嘗試發貨):assertThrows(IllegalStateException.class, () -> order.deliver());
- 參數化測試
覆蓋所有狀態組合,減少重復代碼:
@ParameterizedTest
@EnumSource(ElevatorState.class)
void testAllStates(ElevatorState state) {ElevatorContext context = new ElevatorContext(state);context.request();// 驗證狀態轉換邏輯
}
三、測試最佳實踐
- 獨立性:每個測試用例初始化獨立上下文,避免狀態污染。
- 模擬外部依賴:用Mockito替代數據庫或網絡請求(如模擬訂單支付接口)。
- 覆蓋率:確保覆蓋所有狀態轉換路徑(如紅燈→綠燈→黃燈→紅燈)。
四、常見問題與解決方案
問題 | 解決方案 |
---|---|
狀態切換未觸發 | 檢查狀態類是否正確調用context.setState() 。 |
測試用例間依賴 | 使用@Before 注解重置上下文狀態。 |
狀態轉換邏輯遺漏 | 通過狀態機工具(如Spring StateMachine)可視化驗證轉換規則。 |
五、總結
狀態模式通過對象化狀態與委托機制實現了行為與狀態的解耦,而單元測試則通過模擬框架與斷言驗證確保了狀態轉換的可靠性。實際開發中,結合Mockito進行隔離測試,可顯著提升代碼質量與維護效率。