什麼是狀態模式
狀態模式允許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類一樣。
狀態模式應用場景
1.一個對象的行爲取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行爲。
2.操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。 通常,有多個操作包含這一相同的條件結構。State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作爲一個對象,這一對象可以不依賴於其他對象而獨立變化。
狀態模式實現
需要重構的代碼
public class OrderService {
public String orderState(String state) {
if (state.equals("0")) {
return "已經發貨";
}
if (state.equals("1")) {
return "正在運送中...";
}
if (state.equals("2")) {
return "正在派送中...";
}
if (state.equals("3")) {
return "已經簽收";
}
if (state.equals("4")) {
return "拒絕簽收";
}
if (state.equals("5")) {
return "訂單交易失敗";
}
return "未找到對應的狀態";
}
}
狀態模式與策略模式區別
策略模式結構圖:
狀態模式結構圖
1、狀態模式重點在各狀態之間的切換從而做不同的事情,而策略模式更側重於根據具體情況選擇策略,並不涉及切換。
2、狀態模式不同狀態下做的事情不同,而策略模式做的都是同一件事,例如聚合支付平臺,有支付寶、微信支付、銀聯支付,雖然策略不同,但最終做的事情都是支付,也就是說他們之間是可替換的。反觀狀態模式,各個狀態的同一方法做的是不同的事,不能互相替換。
狀態模式封裝了對象的狀態,而策略模式封裝算法或策略。因爲狀態是跟對象密切相關的,它不能被重用;而通過從Context中分離出策略或算法,我們可以重用它們。
在狀態模式中,每個狀態通過持有Context的引用,來實現狀態轉移;但是每個策略都不持有Context的引用,它們只是被Context使用。
狀態模式實現
OrderState 定義統一抽象接口
public interface OrderState {
/**
* 返回都會不一樣
*
* @return
*/
public Object orderService();
}
OrderState 實現類:AlreadySignedOrderState
@Slf4j
@Component
public class AlreadySignedOrderState implements OrderState {
@Override
public Object orderService() {
log.info(">> 切換已經簽收狀態");
return "切換已經簽收狀態";
}
}
OrderState 實現類:InTransitOrderState
@Slf4j
@Component
public class InTransitOrderState implements OrderState {
@Override
public String orderService() {
log.info(">>>切換爲正在運送狀態...");
return "success";
}
}
OrderState 實現類:ShippedAlreadyOrderState
@Slf4j
@Component
public class ShippedAlreadyOrderState implements OrderState {
public String orderService() {
log.info(">>>切換爲已經發貨狀態..");
return "已經發貨..";
}
}
Context上下文:StateContext
public class StateContext {
private OrderState orderState;
public StateContext(OrderState orderState) {
this.orderState = orderState;
}
public void switchStateOrder() {
orderState.orderService();
}
}
OrderController
@RestController
public class OrderController {
@RequestMapping("/order")
public String order(String stateBeanId) {
//1.使用Spring上下文獲取bean中對象
OrderState orderState = SpringUtils.getBean(stateBeanId, OrderState.class);
// 2.使用上下文切換到不同的狀態
StateContext stateContext = new StateContext(orderState);
stateContext.switchStateOrder();
// 如果寫多重if判斷的話 整個代碼流程 耗時比較長 直接Spring中精準定位到策略或者是狀態的話 Map get方法的時候底層是數組
return "success";
}
}
SpringUtils
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
//獲取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通過name獲取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通過class獲取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通過name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
pom依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<!-- sprinboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
啓動類
@SpringBootApplication
public class AppOrderState {
public static void main(String[] args) {
SpringApplication.run(AppOrderState.class);
}
}
測試結果
訪問:http://127.0.0.1:8080/order?stateBeanId=alreadySignedOrderState
控制檯輸出:>> 切換已經簽收狀態
訪問:http://127.0.0.1:8080/order?stateBeanId=inTransitOrderState
控制檯輸出:>>>切換爲正在運送狀態...
訪問:http://127.0.0.1:8080/order?stateBeanId=shippedAlreadyOrderState
控制檯輸出:>>>切換爲已經發貨狀態..
版權@須臾之餘https://my.oschina.net/u/3995125
本文參考:螞蟻課堂:http://www.mayikt.com