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

什麼是狀態模式

狀態模式允許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類一樣。

狀態模式應用場景

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章