狀態模式

狀態模式(State):當一個對象的內在狀態g改變時容許改變其行爲,這個對象看起來像是改變了其類。
狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的狀況。把狀態的判斷邏輯轉移到表示不一樣狀態的一系列l類當中,能夠把複雜的判斷邏輯簡化。固然,若是這個狀態判斷很簡單,那就不必用‘狀態模式’。--《大話設計模式》

 

Context: 環境類。能夠包括一些內部狀態。 
State: 抽象狀態類。State定義了一個全部具體狀態的共同接口,任何狀態都實現這個相同的接口,這樣一來,狀態之間就能夠互相轉換了。 
ConcreteState: 具體狀態類。具體狀態類,用於處理來自Context的請求,每個ConcreteState都提供了它對本身請求的實現,因此,當Context改變狀態時行爲也會跟着改變。
 
接下來,用一個酒店房間的例子介紹狀態模式。

 

 當你第一眼看到這個系統的時候你就看出來了這是一個狀態圖,每一個框框都表明了房間的狀態,箭頭表示房間狀態的轉換。分析以下:房間有三個狀態:空閒、已預訂、已入住,狀態與狀態之間能夠根據客戶的動做來進行轉換。定義每一個狀態的值。設計模式

 

 

狀態接口ide

package state;
/**
*
* Title: State
* Description: 狀態接口
* @author yacong_liu Email:2682505646@qq.com
* @date 2019年1月16日
*/
public interface State {
    
    /**
     *
     * <p>Title: bookRoom</p>
     * <p>Description: 預約房間</p>
     */
    void bookRoom();
    
    /**
     *
     * <p>Title: unsubscribeRoom</p>
     * <p>Description: 退訂房間</p>
     */
    void unsubscribeRoom();
    
    /**
     *
     * <p>Title: checkInRoom</p>
     * <p>Description: 入住</p>
     */
    void checkInRoom();
    
    /**
     *
     * <p>Title: checkOutRoom</p>
     * <p>Description: 退房</p>
     */
    void checkOutRoom();
    
}

房間測試

package state;
/**
*
* Title: Room Description: 房間
*
* @author yacong_liu Email:2682505646@qq.com
* @date 2019年1月16日
*/
public class Room {
    /*
     * @desc 空閒狀態
     */
    State freeState;
    /*
     * @desc 預訂狀態
     */
    State bookedState;
    /*
     * @desc 入住狀態
     */
    State checkInState;
    State state;
    public Room() {
        this.freeState = new FreeState(this);
        this.bookedState = new BookedState(this);
        this.checkInState = new CheckInState(this);
        // 初始狀態爲空閒狀態
        this.state = freeState;
    }
    /**
     *
     * <p>
     * Title: bookRoom
     * </p>
     * <p>
     * Description: 預訂房間
     * </p>
     */
    public void bookRoom() {
        state.bookRoom();
    }
    /**
     *
     * <p>
     * Title: unsubsribeRoom
     * </p>
     * <p>
     * Description: 退訂房間
     * </p>
     */
    public void unsubsribeRoom() {
        state.unsubscribeRoom();
    }
    /**
     *
     * <p>
     * Title: checkInRoom
     * </p>
     * <p>
     * Description: 入住
     * </p>
     */
    public void checkInRoom() {
        state.checkInRoom();
    }
    /**
     *
     * <p>
     * Title: checkOutRoom
     * </p>
     * <p>
     * Description: 退房
     * </p>
     */
    public void checkOutRoom() {
        state.checkOutRoom();
    }
    /*
     * getter setter
     */
    public State getFreeState() {
        return freeState;
    }
    public void setFreeState(State freeState) {
        this.freeState = freeState;
    }
    public State getBookedState() {
        return bookedState;
    }
    public void setBookedState(State bookedState) {
        this.bookedState = bookedState;
    }
    public State getCheckInState() {
        return checkInState;
    }
    public void setCheckInState(State checkInState) {
        this.checkInState = checkInState;
    }
    public State getState() {
        return state;
    }
    public void setState(State state) {
        this.state = state;
    }
    @Override
    public String toString() {
        return "該房間的狀態是:" + getState().getClass().getName();
    }
}

空閒狀態this

package state;
/**
*
* Title: FreeState Description: 空閒狀態 (可預約和入住)
*
* @author yacong_liu Email:2682505646@qq.com
* @date 2019年1月16日
*/
public class FreeState implements State {
    Room hotelManager;
    public FreeState(Room hotelManager) {
        this.hotelManager = hotelManager;
    }
    @Override
    public void bookRoom() {
        System.out.println("您已經成功預訂了...");
        // 房間狀態切換爲已預約狀態
        hotelManager.setState(hotelManager.getBookedState());
    }
    @Override
    public void unsubscribeRoom() {
        System.out.println("該房間空閒狀態,不接受退訂!");
    }
    @Override
    public void checkInRoom() {
        System.out.println("您已經入住...");
        // 房間狀態切換爲已入住狀態
        hotelManager.setState(hotelManager.getCheckInState());
    }
    @Override
    public void checkOutRoom() {
        System.out.println("該房間空閒狀態,不接受退房!");
    }
}

入住狀態spa

package state;
/**
*
* Title: CheckInState Description: 入住狀態 (只能退房)
*
* @author yacong_liu Email:2682505646@qq.com
* @date 2019年1月16日
*/
public class CheckInState implements State {
    Room hotelManager;
    public CheckInState(Room hotelManager) {
        this.hotelManager = hotelManager;
    }
    @Override
    public void bookRoom() {
        System.out.println("該房間處於入住狀態,再也不接受預約!");
    }
    @Override
    public void unsubscribeRoom() {
        System.out.println("該房間處於入住狀態,不能退訂!");
    }
    @Override
    public void checkInRoom() {
        System.out.println("該房間處於入住狀態,不能在入住!");
    }
    @Override
    public void checkOutRoom() {
        System.out.println("退房成功...");
        // 房間狀態切換爲空閒狀態
        hotelManager.setState(hotelManager.getFreeState());
    }
}

預訂狀態設計

package state;
/**
*
* Title: BookedState Description: 預約狀態(可退訂 入住)
*
* @author yacong_liu Email:2682505646@qq.com
* @date 2019年1月16日
*/
public class BookedState implements State {
    Room hotelManager;
    public BookedState(Room hotelManager) {
        this.hotelManager = hotelManager;
    }
    @Override
    public void bookRoom() {
        System.out.println("該房間已經處於預約狀態,不在接受預約!");
    }
    @Override
    public void unsubscribeRoom() {
        System.out.println("退訂成功,歡迎下次光臨");
        // 房間狀態切換爲空閒狀態
        hotelManager.setState(hotelManager.getFreeState());
    }
    @Override
    public void checkInRoom() {
        System.out.println("入住成功...");
        // 房間狀態切換爲入住狀態
        hotelManager.setState(hotelManager.getCheckInState());
    }
    @Override
    public void checkOutRoom() {
        System.out.println("該房間處於預約狀態,不接受退房!");
    }
}

客戶端測試code

package state;
import org.junit.Test;
public class RoomTest {
    @Test
    public void test() {
        Room[] room = new Room[2];
        for (int i = 0; i < room.length; i++) {
            room[i] = new Room();
        }
        room[0].bookRoom();
        room[0].checkInRoom();
        room[0].bookRoom();
        room[0].checkOutRoom();
    }
}

輸出結果對象

您已經成功預訂了...
入住成功...
該房間處於入住狀態,再也不接受預約!
退房成功...
經過上面的例子,咱們已經對狀態模式有所瞭解,下面咱們作一個總結,來回顧咱們的狀態模式:

 

1.狀態模式容許對象在內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。
   理解:這個模式將狀態封裝成獨立的類,並將動做委託到表明當前狀態的對象,這就是說行爲會隨着內部狀態而改變。
   「看起來好像修改了它的類」是什麼意思呢?從客戶的視角來看:若是說你使用的對象可以徹底改變它的行爲,那麼你會以爲,這個對象其實是從別的類實例化而來的。然而,實際上,你知道咱們是在使用組合經過簡單引用不一樣的狀態對象來形成類改變的假象
2.狀態模式要點

 

(1)客戶不會和狀態進行交互,全盤瞭解狀態是 context的工做
(2)在狀態模式中,每一個狀態經過持有Context的引用,來實現狀態轉移
(3)使用狀態模式老是會增長設計中類的數目,這是爲了要得到程序可擴展性,彈性的代價,若是你的代碼不是一次性的,後期可能會不斷加入不一樣的狀態,那麼狀態模式的設計是絕對值得的。【同時也是一個缺點】
(4)狀態類能夠被多個context實例共享
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息