行爲型模式:狀態模式

景色

十一大行爲型模式之八:狀態模式。java

簡介

姓名 :狀態模式
英文名 :State Pattern
價值觀 :有啥事讓狀態我來維護
我的介紹
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
當一個對象內在狀態改變時容許其改變行爲,這個對象看起來像改變了其類。
(來自《設計模式之禪》)設計模式

你要的故事

如今有好多我的貸款軟件,好比:支付寶、360借條(打廣告。。。)等等。貸款會有一個用戶狀態流程,遊客->註冊用戶->授信用戶->借款用戶(這裏簡化了狀態,只用 4 個)。每一個狀態擁有的權限不同,以下圖所示。app

狀態

從上圖能夠看到,一個用戶有 3 種行爲,分別是註冊、授信、借款。當註冊成功後,用戶的狀態就從『遊客』改變爲『註冊用戶』;當授信成功後,用戶的狀態就從『註冊用戶』改變爲『授信用戶』;當借款成功後,用戶的狀態就從『授信用戶』改變爲『借款用戶』。如今咱們就來實現用戶註冊、授信、借款的過程,由於每一個狀態的權限不同,因此這裏須要根據用戶的狀態來限制用戶行爲。ide

很快,咱們就完成下面的代碼。學習

class User {
    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public void register() {
        if ("none".equals(state)) {
            System.out.println("遊客。註冊中。。。");
        }else if ("register".equals(state)) {
            System.out.println("註冊用戶。不須要再註冊。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用戶。不須要再註冊。");
        } else if ("draw".equals(state)) {
            System.out.println("借款用戶。不須要再註冊。");
        }
    }

    public void apply() {
        if ("none".equals(state)) {
            System.out.println("遊客。不能申請授信。");
        }else if ("register".equals(state)) {
            System.out.println("註冊用戶。授信申請中。。。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用戶。不須要再授信。");
        } else if ("draw".equals(state)) {
            System.out.println("借款用戶。不須要再授信。");
        }
    }

    public void draw(double money) {
        if ("none".equals(state)) {
            System.out.println("遊客。申請借款【" + money + "】元。不能申請借款。");
        } else if ("register".equals(state)) {
            System.out.println("註冊用戶。申請借款【" + money + "】元。還沒授信,不能借款。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。");
        } else if ("draw".equals(state)) {
            System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。");
        }
    }
}

public class NoStateTest {

    public static void main(String[] args) {
        User user = new User();
        user.setState("register");
        user.draw(1000);
    }

}

打印結果:
註冊用戶。申請借款【1000.0】元。還沒授信,不能借款。

上面代碼實現了用戶 register (註冊),apply (授信),draw (借款) 這 3 種行爲,每一個行爲都會根據狀態 state 來作權限控制。看起來有點繁瑣,擴展性不高,假設新增了一個狀態,那麼註冊、授信、借款這 3 種行爲的代碼都要修改。下面經過狀態模式來解決這個問題。this

咱們把狀態給抽出來,做爲一個接口,由於在每種狀態中均可能有註冊、授信、借款行爲,因此把這 3 個行爲做爲狀態接口的方法,讓每一個狀態子類都實現相應的行爲控制。以下代碼所示。設計

interface State {

    void register();

    void apply();

    void draw(double money);
}

/**
 * 遊客
 */
class NoneState implements State {

    @Override
    public void register() {
        System.out.println("遊客。註冊中。。。");
    }

    @Override
    public void apply() {
        System.out.println("遊客。不能申請授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("遊客。申請借款【" + money + "】元。不能申請借款。");
    }
}

/**
 * 註冊狀態
 */
class RegisterState implements State {

    @Override
    public void register() {
        System.out.println("註冊用戶。不須要再註冊。");
    }

    @Override
    public void apply() {
        System.out.println("註冊用戶。授信申請中。。。");
    }

    @Override
    public void draw(double money) {
        System.out.println("註冊用戶。申請借款【" + money + "】元。還沒授信,不能借款。");
    }
}

/**
 * 授信狀態
 */
class ApplyState implements State {

    @Override
    public void register() {
        System.out.println("授信用戶。不須要再註冊。");
    }

    @Override
    public void apply() {
        System.out.println("授信用戶。不須要再授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("授信用戶。申請借款【" + money + "】元。申請借款中。。。");
    }
}

/**
 * 借款狀態
 */
class DrawState implements State {

    @Override
    public void register() {
        System.out.println("借款用戶。不須要再註冊。");
    }

    @Override
    public void apply() {
        System.out.println("借款用戶。不須要再授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("申請借款【" + money + "】元。申請借款中。。。");
    }
}

class User1 {
    private State state;

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void register() {
        this.state.register();
    }

    public void apply() {
        this.state.apply();
    }

    public void draw(double money) {
        this.state.draw(money);
    }
}

public class StateTest {
    public static void main(String[] args) {
        User1 user1 = new User1();
        user1.setState(new RegisterState());
        user1.apply();
        user1.draw(1000);
        user1.setState(new ApplyState());
        user1.draw(2000);
    }

}


打印結果:
註冊用戶。授信申請中。。。
註冊用戶。申請借款【1000.0】元。還沒授信,不能借款。
授信用戶。申請借款【2000.0】元。申請借款中。。。

看上面代碼,咱們抽象了 State 接口,4 種狀態分別用 NoneState (遊客)、RegisterState (註冊)、ApplyState (授信)、DrawState (借款) 表示。而每一個狀態都有 3 種行爲,它們各自對這些行爲進行權限控制。這樣子實現可讓權限邏輯分離開,分散到每一個狀態裏面去,若是之後要業務擴展,要新增狀態,那就很方便了,只須要再實現一個狀態類就能夠,不會影響到其餘代碼。這也是爲何《阿里巴巴 Java 開發手冊》裏面講的,當超過 3 層的 if-else 的邏輯判斷代碼,推薦用狀態模式來重構代碼。code

總結

狀態模式 很好的減低了代碼的複雜性,從而提升了系統的可維護性。在業務開發中能夠嘗試使用,好比在迭代開發中,業務邏輯愈來愈複雜,從而不得不使用不少 if-else 語句來實現時,就能夠考慮一下是否是能夠用 狀態模式 來重構,特別是一些有狀態流程轉換方面的業務。看到這篇文章,想一想工做中是否是有些複雜的代碼能夠重構,趕忙行動起來。對象

推薦閱讀:接口

行爲型模式:觀察者模式

行爲型模式:迭代器模式

行爲型模式:策略模式

設計模式系列文章持續更新中,歡迎關注公衆號 LieBrother,一塊兒交流學習。

相關文章
相關標籤/搜索