狀態模式容許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類同樣。web
1.一個對象的行爲取決於它的狀態,而且它必須在運行時刻根據狀態改變它的行爲。算法
2.操做中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態一般用一個或多個枚舉常量表示。 一般,有多個操做包含這一相同的條件結構。State模式將每個條件分支放入一個獨立的類中。這使得你能夠根據對象自身的狀況將對象的狀態做爲一個對象,這一對象能夠不依賴於其餘對象而獨立變化。spring
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 "未找到對應的狀態"; } }
策略模式結構圖:設計模式
狀態模式結構圖數組
一、狀態模式重點在各狀態之間的切換從而作不一樣的事情,而策略模式更側重於根據具體狀況選擇策略,並不涉及切換。微信
二、狀態模式不一樣狀態下作的事情不一樣,而策略模式作的都是同一件事,例如聚合支付平臺,有支付寶、微信支付、銀聯支付,雖然策略不一樣,但最終作的事情都是支付,也就是說他們之間是可替換的。反觀狀態模式,各個狀態的同一方法作的是不一樣的事,不能互相替換。app
狀態模式封裝了對象的狀態,而策略模式封裝算法或策略。由於狀態是跟對象密切相關的,它不能被重用;而經過從Context中分離出策略或算法,咱們能夠重用它們。ide
在狀態模式中,每一個狀態經過持有Context的引用,來實現狀態轉移;可是每一個策略都不持有Context的引用,它們只是被Context使用。spring-boot
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