首页 > 代码库 > 状态模式
状态模式
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); } }
(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; } }
(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); } } } }
(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); } } } }
(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(); } } } } }
(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("--------------------------------------"); } }
4.优缺点
优点:
(1)封装了转换规则,具有多状态的对象当状态发生改变时能够自动切换状态
(2)枚举可能的状态,但要确定状态的种类
(3)能够方便地新增新的状态,只需要改变对象状态就可以改变对象的行为
(4)可以避免使用庞大的if...else语句块去改变状态
(5)可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数
缺点:
(1)状态模式的使用必然会增加系统中类和对象的个数,在一定程度上会增加系统的复杂度
(2)状态模式的实现较为复杂,如果使用不恰当会造成程序结构和代码混乱
(3)状态模式对”开闭原则“支持并不太好,新增状态类时可能要适当地修改原有的状态类的转换逻辑
Practice makes perfect!
状态模式