亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

服務(wù)端指南 | 狀態(tài)機設(shè)計

AWang / 1906人閱讀

摘要:我們以登錄場景設(shè)計一個狀態(tài)機。第三步,定義狀態(tài)機配置,設(shè)置初始狀態(tài),以及狀態(tài)與事件之間的關(guān)系。

原文地址:梁桂釗的博客

博客地址:http://blog.720ui.com/

狀態(tài)機中,每個狀態(tài)有著相應(yīng)的行為,隨著行為的觸發(fā)來切換狀態(tài)。其中一種做法是使用二維數(shù)組實現(xiàn)狀態(tài)機機制,其中橫坐標表示行為,縱坐標表示狀態(tài),具體的數(shù)值則表示當前的狀態(tài)。

我們以登錄場景設(shè)計一個狀態(tài)機。

這時,我們設(shè)計一張狀態(tài)機表。

那么,此時它的二維數(shù)組,如下所示。

此外,我們也可以通過狀態(tài)模式實現(xiàn)一個狀態(tài)機。狀態(tài)模式將每一個狀態(tài)封裝成獨立的類,具體行為會隨著內(nèi)部狀態(tài)而改變。狀態(tài)模式用類表示狀態(tài),這樣我們就能通過切換類來方便地改變對象的狀態(tài),避免了冗長的條件分支語句,讓系統(tǒng)具有更好的靈活性和可擴展性。

現(xiàn)在,我們定義一個狀態(tài)枚舉,其中包括未連接、已連接、注冊中、已注冊 4 種狀態(tài)。

public enum StateEnum {
    // 未連接
    UNCONNECT(1, "UNCONNECT"), 
    // 已連接
    CONNECT(2, "CONNECT"), 
    // 注冊中
    REGISTING(3, "REGISTING"), 
    // 已注冊
    REGISTED(4, "REGISTED");
    
    private int key;
    private String value;

    StateEnum(int key, String value) {
        this.key = key;
        this.value = value;
    }
    public int getKey() {return key;}
    public String getValue() {return value;}
}

定義一個環(huán)境類,它是實際上是真正擁有狀態(tài)的對象。

public class Context {
    private State state;
    public void connect(){
        state.connect(this);
        System.out.println("STATE : " + state.getCurState());
    } 
    public void register(){
        state.register(this);
        System.out.println("STATE : " + state.getCurState());
    }   
    public void registerSuccess(){
        state.registerSuccess(this);
        System.out.println("STATE : " + state.getCurState());
    }
    public void registerFailed(){
        state.registerFailed(this);
        System.out.println("STATE : " + state.getCurState());
    }
    public void unRegister(){
        state.unRegister(this);
        System.out.println("STATE : " + state.getCurState());
    }
    public State getState() {
        return state;
    }
    public void setState(State state) {
        this.state = state;
    }
}

狀態(tài)模式用類表示狀態(tài),這樣我們就能通過切換類來方便地改變對象的狀態(tài)?,F(xiàn)在,我們定義幾個狀態(tài)類。

public interface State {
    void connect(Context c);
    void register(Context c);
    void registerSuccess(Context c);
    void registerFailed(Context c);
    void unRegister(Context c);
    String getCurState();
}

public class UnconnectState implements State {
    @Override
    public void connect(Context c) {
        c.setState(new ConnectState());
    }
    @Override
    public void register(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void registerSuccess(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void registerFailed(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void unRegister(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public String getCurState() {
        return StateEnum.UNCONNECT.toString();
    }
}

public class ConnectState implements State {
    @Override
    public void connect(Context c) {
        c.setState(new ConnectState());
    }
    @Override
    public void register(Context c) {
        c.setState(new RegistingState());
    }
    @Override
    public void registerSuccess(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void registerFailed(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void unRegister(Context c) {
        c.setState(new UnconnectState());
    }
    @Override
    public String getCurState() {
        return StateEnum.CONNECT.toString();
    }
}

public class RegistingState implements State {
    @Override
    public void connect(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void register(Context c) {
        c.setState(new RegistingState());
    }
    @Override
    public void registerSuccess(Context c) {
        c.setState(new RegistedState());
    }
    @Override
    public void registerFailed(Context c) {
        c.setState(new UnconnectState());
    }
    @Override
    public void unRegister(Context c) {
        c.setState(new UnconnectState());
    }
    @Override
    public String getCurState() {
        return StateEnum.REGISTING.toString();
    }
}

public class RegistedState implements State {
    @Override
    public void connect(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void register(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void registerSuccess(Context c) {
        c.setState(new RegistedState());
    }
    @Override
    public void registerFailed(Context c) {
        throw new RuntimeException("INVALID_OPERATE_ERROR");
    }
    @Override
    public void unRegister(Context c) {
        c.setState(new UnconnectState());
    }
    @Override
    public String getCurState() {
        return StateEnum.REGISTED.toString();
    }
}

注意的是,如果某個行為不會觸發(fā)狀態(tài)的變化,我們可以拋出一個 RuntimeException 異常。此外,調(diào)用時,通過環(huán)境類控制狀態(tài)的切換,如下所示。

public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.connect();
        context.register();
    }
}

Spring StateMachine 讓狀態(tài)機結(jié)構(gòu)更加層次化,可以幫助開發(fā)者簡化狀態(tài)機的開發(fā)過程?,F(xiàn)在,我們來用 Spring StateMachine 進行改造。修改 pom 文件,添加 Maven 依賴。


    org.springframework.statemachine
    spring-statemachine-core
    1.2.0.RELEASE

定義一個狀態(tài)枚舉,其中包括未連接、已連接、注冊中、已注冊 4 種狀態(tài)。

public enum RegStatusEnum {
    // 未連接
    UNCONNECTED,
    // 已連接
    CONNECTED,
    // 注冊中
    REGISTERING,
    // 已注冊
    REGISTERED;
}

定義一個行為枚舉,其中包括連接、注冊、注冊成功、注冊失敗、注銷 5 種行為事件。

public enum RegEventEnum {
    // 連接
    CONNECT,
    // 注冊
    REGISTER,
    // 注冊成功
    REGISTER_SUCCESS,
    // 注冊失敗
    REGISTER_FAILED,
    // 注銷
    UN_REGISTER;
}

接著,我們需要進行狀態(tài)機配置,其中 @EnableStateMachine 注解,標識啟用 Spring StateMachine 狀態(tài)機功能。

@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter {
}

我們需要初始化狀態(tài)機的狀態(tài)。其中,initial(RegStatusEnum.UNCONNECTED) 定義了初始狀態(tài)是未連接狀態(tài)。states(EnumSet.allOf(RegStatusEnum.class)) 定義了狀態(tài)機中存在的所有狀態(tài)。

@Override
public void configure(StateMachineStateConfigurer states) throws Exception {
    states.withStates()
    // 定義初始狀態(tài)
    .initial(RegStatusEnum.UNCONNECTED)
    // 定義狀態(tài)機狀態(tài)
    .states(EnumSet.allOf(RegStatusEnum.class));
}

我們需要初始化當前狀態(tài)機有哪些狀態(tài)事件。其中, source 指定原始狀態(tài),target 指定目標狀態(tài),event 指定觸發(fā)事件。

@Override
public void configure(StateMachineTransitionConfigurer transitions)
        throws Exception {
        // 1.連接事件
        // 未連接 -> 已連接
        .withExternal()
            .source(RegStatusEnum.UNCONNECTED)
            .target(RegStatusEnum.CONNECTED)
            .event(RegEventEnum.CONNECT)
        .and() 
        .withExternal()
            .source(RegStatusEnum.CONNECTED)
            .target(RegStatusEnum.CONNECTED)
            .event(RegEventEnum.CONNECT)
        .and()                    
 
        // 2.注冊事件   
        // 已連接 -> 注冊中
        .withExternal()
            .source(RegStatusEnum.CONNECTED)
            .target(RegStatusEnum.REGISTERING)
            .event(RegEventEnum.REGISTER)
        .and()
       .withExternal()
            .source(RegStatusEnum.REGISTERING)
            .target(RegStatusEnum.REGISTERING)
            .event(RegEventEnum.REGISTER)
        .and() 
        
        // 3.注冊成功事件   
        // 注冊中 -> 已注冊
        .withExternal()
            .source(RegStatusEnum.REGISTERING)
            .target(RegStatusEnum.REGISTERED)
            .event(RegEventEnum.REGISTER_SUCCESS)
        .and()
        .withExternal()
            .source(RegStatusEnum.REGISTERED)
            .target(RegStatusEnum.REGISTERED)
            .event(RegEventEnum.REGISTER_SUCCESS)
        .and()
        
         // 4.注冊失敗事件   
        // 注冊中 -> 未連接
        .withExternal()
            .source(RegStatusEnum.REGISTERING)
            .target(RegStatusEnum.UNCONNECTED)
            .event(RegEventEnum.REGISTER_FAILED)
        .and()
        
        // 5.注銷事件
        // 已連接 -> 未連接
        .withExternal()
            .source(RegStatusEnum.CONNECTED)
            .target(RegStatusEnum.UNCONNECTED)
            .event(RegEventEnum.UN_REGISTER)
        .and()
        // 注冊中 -> 未連接
        .withExternal()
            .source(RegStatusEnum.REGISTERING)
            .target(RegStatusEnum.UNCONNECTED)
            .event(RegEventEnum.UN_REGISTER)
        .and()
        // 已注冊 -> 未連接
        .withExternal()
            .source(RegStatusEnum.REGISTERED)
            .target(RegStatusEnum.UNCONNECTED)
            .event(RegEventEnum.UN_REGISTER)
        ;
}

Spring StateMachine 提供了注解配置實現(xiàn)方式,所有 StateMachineListener 接口中定義的事件都能通過注解的方式來進行配置實現(xiàn)。這里以連接事件為案例,@OnTransition 中 source 指定原始狀態(tài),target 指定目標狀態(tài),當事件觸發(fā)時將會被監(jiān)聽到從而調(diào)用 connect() 方法。

@WithStateMachine
public class StateMachineEventConfig {
 
    @OnTransition(source = "UNCONNECTED", target = "CONNECTED")
    public void connect() {
        System.out.println("http:///////////////////");
        System.out.println("連接事件, 未連接 -> 已連接");
        System.out.println("http:///////////////////");
    }
 
    @OnTransition(source = "CONNECTED", target = "REGISTERING")
    public void register() {
        System.out.println("http:///////////////////");
        System.out.println("注冊事件, 已連接 -> 注冊中");
        System.out.println("http:///////////////////");
    }
 
    @OnTransition(source = "REGISTERING", target = "REGISTERED")
    public void registerSuccess() {
        System.out.println("http:///////////////////");
        System.out.println("注冊成功事件, 注冊中 -> 已注冊");
        System.out.println("http:///////////////////");
    }
 
    @OnTransition(source = "REGISTERED", target = "UNCONNECTED")
    public void unRegister() {
        System.out.println("http:///////////////////");
        System.out.println("注銷事件, 已注冊 -> 未連接");
        System.out.println("http:///////////////////");
    }
}

Spring StateMachine 讓狀態(tài)機結(jié)構(gòu)更加層次化,我們來回顧下幾個核心步驟:第一步,定義狀態(tài)枚舉。第二步,定義事件枚舉。第三步,定義狀態(tài)機配置,設(shè)置初始狀態(tài),以及狀態(tài)與事件之間的關(guān)系。第四步,定義狀態(tài)監(jiān)聽器,當狀態(tài)變更時,觸發(fā)方法。

(完)

更多精彩文章,盡在「服務(wù)端思維」微信公眾號!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/68216.html

相關(guān)文章

  • 2019 - Web開發(fā)技術(shù)指南和趨勢

    摘要:以下內(nèi)容來自我特別喜歡的一個頻道這是一個年你成為前端,后端或全棧開發(fā)者的進階指南你不需要學(xué)習(xí)所有的技術(shù)成為一個開發(fā)者這個指南只是通過簡單分類列出了技術(shù)選項我將從我的經(jīng)驗和參考中給出建議首選我們會介紹通用的知識最后介紹年的的一些趨勢基礎(chǔ)前端開 以下內(nèi)容來自我特別喜歡的一個Youtube頻道: Traversy Media 這是一個2019年你成為前端,后端或全棧開發(fā)者的進階指南: 你...

    sourcenode 評論0 收藏0
  • 架構(gòu)

    摘要:分布式架構(gòu)實踐負載均衡在網(wǎng)站創(chuàng)立初期,我們一般都使用單臺機器對臺提供集中式服務(wù),但是隨著業(yè)務(wù)量越來越大,無論是性能上還是穩(wěn)定性上都有了更大的挑戰(zhàn)。就鹿晗宣布戀情導(dǎo)致微博宕機事件淺談大型網(wǎng)站高可用性架構(gòu)中午吃飯刷著刷著微博發(fā)現(xiàn)微博突然掛了。 分布式架構(gòu)實踐——負載均衡 在網(wǎng)站創(chuàng)立初期,我們一般都使用單臺機器對臺提供集中式服務(wù),但是隨著業(yè)務(wù)量越來越大,無論是性能上還是穩(wěn)定性上都有了更大的挑...

    Pink 評論0 收藏0
  • Java入坑指南

    摘要:入坑指南是滴,下面是一個最低的入坑還應(yīng)該有種設(shè)計模式應(yīng)該掌握的。堆棧以幀為單位保存線程的狀態(tài),對堆棧的操作為壓棧和出棧執(zhí)行字節(jié)碼以后,將會產(chǎn)生程序計數(shù)器和棧,程序計數(shù)器存放將要執(zhí)行下一條指令的偏移量。 Java入坑指南是滴,下面是一個最低的入坑 還應(yīng)該有23種設(shè)計模式應(yīng)該掌握的。╮(╯▽╰)╭注意,第一個j是大寫。 Java的特點跨平臺,風(fēng)格接近C++最重要的api文檔 https:/...

    Rindia 評論0 收藏0
  • 好書閱讀與推薦(續(xù)四)

    摘要:后端好書閱讀與推薦系列文章后端好書閱讀與推薦后端好書閱讀與推薦續(xù)后端好書閱讀與推薦續(xù)二后端好書閱讀與推薦續(xù)三后端好書閱讀與推薦續(xù)四這里依然記錄一下每本書的亮點與自己讀書心得和體會,分享并求拍磚。 后端好書閱讀與推薦系列文章:后端好書閱讀與推薦后端好書閱讀與推薦(續(xù))后端好書閱讀與推薦(續(xù)二)后端好書閱讀與推薦(續(xù)三)后端好書閱讀與推薦(續(xù)四) 這里依然記錄一下每本書的亮點與自己讀書心得...

    phodal 評論0 收藏0
  • spring statemachine的企業(yè)可用級開發(fā)指南7-偽持久化和中間段狀態(tài)

    摘要:在實際的企業(yè)開發(fā)中,不可能所有情況都是從頭到尾的按狀態(tài)流程來,會有很多意外,比如歷史數(shù)據(jù),故障重啟后的遺留流程,所以這種可以任意調(diào)節(jié)狀態(tài)的才是我們需要的狀態(tài)機。 1、偽持久化和中間段的狀態(tài)機我們設(shè)想一個業(yè)務(wù)場景,就比如訂單吧,我們一般的設(shè)計都會把訂單狀態(tài)存到訂單表里面,其他的業(yè)務(wù)信息也都有表保存,而狀態(tài)機的主要作用其實是規(guī)范整個訂單業(yè)務(wù)流程的狀態(tài)和事件,所以狀態(tài)機要不要保存真的不重要,...

    shiyang6017 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<