真實項目案例實戰——【狀態設計模式】使用場景

寫在前面:設計模式源於生活,而又高於生活!

什麼是狀態模式

狀態模式容許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類同樣。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

相關文章
相關標籤/搜索