手记

java设计模式--状态模式

状态模式:允许对象在内部状态发生改变时改变他的行为,对象看起来好像修改了它的类。
状态模式的uml图如下:

状态模式包括以下角色:
Context类:环境类,包括一些内部状态。
State类—抽象状态类,state定义的一个所有的具体状态的共同接口,任何状态都能实现这个接口,这样一来状态之间可以互相转换。
ConcreteState类:具体的状态类。用于处理来自Context的请求,每一个ConcreteState都实现了context一个状态相关的行为,所以当context改变状态时,行为也会跟着改变。

例如,酒店的房间有预定,退订,入住,退房等各种状态。

每一个单元代表房间的一种状态,箭头指向代表房间状态的转换。
酒店的uml图:

对应的状态接口:

package com.hy.state;

public interface State {  
    /**  
     * @desc 预订房间  
     * @return void  
     */  
    public void bookRoom();  

    /**  
     * @desc 退订房间  
     * @return void  
     */  
    public void unsubscribeRoom();  

    /**  
     * @desc 入住  
     * @return void  
     */  
    public void checkInRoom();  

    /**  
     * @desc 退房  
     * @return void  
     */  
    public void checkOutRoom();  

} 

房间类:

package com.hy.state;

public class Room {  
    /*  
     * 房间的三个状态  
     */  
    State freeTimeState;    //空闲状态  
    State checkInState;     //入住状态  
    State bookedState;      //预订状态  

    State state ;    

    public Room(){  
        freeTimeState = new FreeTimeState(this);  
        checkInState = new CheckInState(this);  
        bookedState = new BookedState(this);  

        state = freeTimeState ;  //初始状态为空闲  
    }  

    /**  
     * @desc 预订房间  
     * @return void  
     */  
    public void bookRoom(){  
        state.bookRoom();  
    }  

    /**  
     * @desc 退订房间  
     * @return void  
     */  
    public void unsubscribeRoom(){  
        state.unsubscribeRoom();  
    }  

    /**  
     * @desc 入住  
     * @return void  
     */  
    public void checkInRoom(){  
        state.checkInRoom();  
    }  

    /**  
     * @desc 退房  
     * @return void  
     */  
    public void checkOutRoom(){  
        state.checkOutRoom();  
    }  

    public String toString(){  
        return "该房间的状态是:"+getState().getClass().getName();  
    }  

    /*  
     * getter和setter方法略  
     */  
      ...
} 

三个状态类:

package com.hy.state;

/**  
 * @project: design_state  
 * @date 2013-8-24  
 * @Description: 预定状态房间只能退定
 */  
public class BookedState implements State {  
    Room hotelManagement;  

    public BookedState(Room hotelManagement) {  
        this.hotelManagement = hotelManagement;  
    }  

    public void bookRoom() {  
        System.out.println("该房间已近给预定了...");  
    }  

    public void checkInRoom() {  
        System.out.println("入住成功...");   
        hotelManagement.setState(hotelManagement.getCheckInState());         //状态变成入住  
    }  

    public void checkOutRoom() {  
        //不需要做操作  
    }  

    public void unsubscribeRoom() {  
        System.out.println("退订成功,欢迎下次光临...");  
        hotelManagement.setState(hotelManagement.getFreeTimeState());   //变成空闲状态  
    }  

}  
package com.hy.state;

/**  
 * @project: design_state   
 * @date 2013-8-24  
 * @Description: 入住可以退房 
 */  
public class CheckInState implements State {  
    Room hotelManagement;  
    public CheckInState(Room hotelManagement) {  
        this.hotelManagement = hotelManagement;  
    }  

    public void bookRoom() {  
        System.out.println("该房间已经入住了...");  
    }  

    public void checkInRoom() {  
        System.out.println("该房间已经入住了...");  
    }  

    public void checkOutRoom() {  
        System.out.println("退房成功....");  
        hotelManagement.setState(hotelManagement.getFreeTimeState());     //状态变成空闲  
    }  

    public void unsubscribeRoom() {  
        //不需要做操作  
    }  

} 
package com.hy.state;
/**  
 * @project: design_state   
 * @date 2013-8-24  
 * @Description: 空闲状态只能预订和入住 
 */  
public class FreeTimeState implements State {  

    Room hotelManagement;  

    public FreeTimeState(Room hotelManagement){  
        this.hotelManagement = hotelManagement;  
    }  

    public void bookRoom() {  
        System.out.println("您已经成功预订了...");  
        hotelManagement.setState(hotelManagement.getBookedState());   //状态变成已经预订  
    }  

    public void checkInRoom() {  
        System.out.println("您已经成功入住了...");  
        hotelManagement.setState(hotelManagement.getCheckInState());   //状态变成已经入住  
    }  

    public void checkOutRoom() {  
        //不需要做操作  
    }  

    public void unsubscribeRoom() {  
        //不需要做操作  
    }  

}  

测试类:

package com.hy.state;

public class Test {  
    public static void main(String[] args) {  
        //有2间房  
        Room[] rooms = new Room[2];  
        //初始化  
        for(int i = 0 ; i < rooms.length ; i++){  
            rooms[i] = new Room();  
        }  
        //第一间房  
        rooms[0].bookRoom();    //预订  
        rooms[0].checkInRoom();   //入住  
        rooms[0].bookRoom();    //预订  
        System.out.println(rooms[0]);  
        System.out.println("---------------------------");  

        //第二间房  
        rooms[1].checkInRoom();  
        rooms[1].bookRoom();  
        rooms[1].checkOutRoom();  
        rooms[1].bookRoom();  
        System.out.println(rooms[1]);  
    }  

}  

状态模式主要解决的是
当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列的类中,可以把复杂逻辑简化。

即当对象的行为取决于它的状态时,并且必须在运行时刻根据状态改变他的行为时,可以考虑使用状态模式。

状态模式的好处是 :
将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
特定状态的相关的行为都放入一个对象中,由于所有的与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类,可以很容易的增加新的状态和转换。
而且消除了庞大的条件分支语句,通过各种状态把逻辑分布到state的子类之中,来减少相互之间的依赖。

注意:使用前需要枚举可能的状态,否则可能也会有一些工作量。例如新增一个预留状态,除了新增一个预留状态ConcreteState类,还需要在状态State接口中新增预留接口,Room类中新增预留状态,各个ConcreteState接口类增加与预留状态相互的关系行为。

这也大致体现了状态模式的缺点,必然性的会增加系统中类和对象的个数。使用不当会导致系统的复杂性增加。如果预先状态设计不能全面,对开闭原则支持的就不太好,对于互相切换状态的系统,新增新的状态会修改那些负责状态转换和对应类的代码。

1人推荐
随时随地看视频
慕课网APP