首页 > 代码库 > 状态模式

状态模式

  1.定义

    允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。例如:在一个停车场

  有很多的停车位,停车位有三种状态,分别是忙碌,空闲,维护。如果不使用状态模式的话,那么状态的改

  是停车位去维护,这样的话不符合单一自责原则,停车位的职责过重,而且如果新增状态要修改停车位的代

  码,也违背了开闭原则。正确的做法是将状态抽象出来,停车位的状态改变让具体的状态类去维护,这样的

  话就更加具有灵活性。

  2.模式结构

  技术分享

  (1)多状态类:ParkingSeat

  (2)抽象状态:ParkingSeatState

  (3)具体状态类:BusyParkingSeatState(忙碌)FreeParkingSeatState(空闲)MaintainParkingSeatState(维护)

  3.代码

  (1)ParkingSeat.java

技术分享
package com.uptowncat.state;

/**
 * 停车位
 * 
 * @author Administrator
 * 
 */
public class ParkingSeat {
    private int id;
    private String sequenceNum;
    private ParkingSeatState state;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSequenceNum() {
        return sequenceNum;
    }

    public void setSequenceNum(String sequenceNum) {
        this.sequenceNum = sequenceNum;
    }

    public ParkingSeatState getState() {
        return state;
    }

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

    public ParkingSeat(int id, String sequenceNum, ParkingSeatState state) {
        super();
        this.id = id;
        this.sequenceNum = sequenceNum;
        this.state = state;
    }
    /**
     * 状态转换:0 busy, 1 free, 2 maintain
     * @param stateNum
     */
    public void change(int stateNum) {
        state.change(stateNum);
    }
}
ParkingSeat.java

  (2)ParkingSeatState.java

技术分享
package com.uptowncat.state;
/**
 * 抽象的停车位状态
 * @author Administrator
 *
 */
public abstract class ParkingSeatState {
    
    protected String name;
    protected ParkingSeat seat;

    public void change(int stateNum) {
        // TODO Auto-generated method stub
        check(stateNum);
    }
    
    public abstract void check(int stateNum);

    public ParkingSeatState(String name, ParkingSeat seat) {
        super();
        this.name = name;
        this.seat = seat;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ParkingSeat getSeat() {
        return seat;
    }

    public void setSeat(ParkingSeat seat) {
        this.seat = seat;
    }
    
    
    
    
}
ParkingSeatState.java

  (3)FreeParkingSeatState.java

技术分享
package com.uptowncat.state;
/**
 * 空闲状态
 * @author Administrator
 *
 */
public class FreeParkingSeatState extends ParkingSeatState {

    public FreeParkingSeatState(String name, ParkingSeat seat) {
        super(name, seat);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void check(int stateNum) {
        // TODO Auto-generated method stub
        if(stateNum == 0) {
            ParkingSeatState busyState = new BusyParkingSeatState("busy", seat);
            seat.setState(busyState);
        }else {
            if(stateNum == 2) {
                ParkingSeatState maintainState = new MaintainParkingSeatState("maintain", seat);
                seat.setState(maintainState);
            }
        }
    }

}
FreeParkingSeatState.java

  (4)BusyParkingSeatState.java

技术分享
package com.uptowncat.state;
/**
 * 忙碌状态
 * @author Administrator
 *
 */
public class BusyParkingSeatState extends ParkingSeatState {

    public BusyParkingSeatState(String name, ParkingSeat seat) {
        super(name, seat);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void check(int stateNum) {
        // TODO Auto-generated method stub
        if(stateNum == 1) {
            ParkingSeatState freeState = new FreeParkingSeatState("free", seat);
            seat.setState(freeState);
        }else {
            if(stateNum == 2) {
                ParkingSeatState maintainState = new MaintainParkingSeatState("maintain", seat);
                seat.setState(maintainState);
            }
        }
    }

}
BusyParkingSeatState.java

  (5)MaintainParkingSeatState.java

技术分享
package com.uptowncat.state;
/**
 * 维护状态
 * @author Administrator
 *
 */
public class MaintainParkingSeatState extends ParkingSeatState{

    public MaintainParkingSeatState(String name, ParkingSeat seat) {
        super(name, seat);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void check(int stateNum) {
        // TODO Auto-generated method stub
        if(stateNum == 1){
            ParkingSeatState freeState = new FreeParkingSeatState("free", seat);
            seat.setState(freeState);
        }else {
            if(stateNum == 0) {
                try {
                    throw new Exception("维护状态不能直接变为忙碌状态!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    

}
MaintainParkingSeatState.java

  (6)Client.java

技术分享
package com.uptowncat.state;

import org.junit.Test;
/**
 * 单元测试
 * @author Administrator
 *
 */
public class Client {
    @Test
    public void test() {
        ParkingSeat parkingSeat = new ParkingSeat(1, "seat A", null);
        ParkingSeatState freeState = new FreeParkingSeatState("free", parkingSeat);
        parkingSeat.setState(freeState);
        System.out.println("初始状态是:");
        print(parkingSeat);
        parkingSeat.change(0);
        print(parkingSeat);
        parkingSeat.change(2);
        print(parkingSeat);
        parkingSeat.change(0);
        print(parkingSeat);
    }
    
    public void print(ParkingSeat parkingSeat) {
        System.out.println(parkingSeat.getSequenceNum() + " 的状态是: " + parkingSeat.getState().getName());
        System.out.println("--------------------------------------");
    }
}
Client.java

  4.优缺点

    优点:

      (1)封装了转换规则,具有多状态的对象当状态发生改变时能够自动切换状态

      (2)枚举可能的状态,但要确定状态的种类

      (3)能够方便地新增新的状态,只需要改变对象状态就可以改变对象的行为

      (4)可以避免使用庞大的if...else语句块去改变状态

      (5)可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数

    缺点:

      (1)状态模式的使用必然会增加系统中类和对象的个数,在一定程度上会增加系统的复杂度

      (2)状态模式的实现较为复杂,如果使用不恰当会造成程序结构和代码混乱

      (3)状态模式对”开闭原则“支持并不太好,新增状态类时可能要适当地修改原有的状态类的转换逻辑

 

 

    Practice makes perfect!

状态模式