状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
结构
- Context环境类
环境类中维护一个State对象,它是定义了当前的状态。 - State抽象状态类
-
ConcreteState具体状态类
每一个类封装了一个状态对应的行为。
状态模式
场景
酒店系统中,房间的状态变化
简单实现
package state;
public abstract class RoomState {
protected RoomContext room;
public abstract void reservation(); // 预定
public abstract void cancel(); // 退订
public abstract void checkIn(); // 入住
public abstract void checkOut(); // 退房
}
package state;
public class FreeState extends RoomState {
public FreeState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("提供手机号,预定成功");
room.setState(room.bookedState);
}
public void cancel() {
System.out.println("房间空闲,无需操作");
}
public void checkIn() {
System.out.println("提供身份证,成功入住");
room.setState(room.checkedInState);
}
public void checkOut() {
System.out.println("房间空闲,无需操作");
}
}
package state;
public class BookedState extends RoomState {
public BookedState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("房间已被预定,不接受其它预定,无需操作");
}
public void cancel() {
System.out.println("提供手机号,退订成功");
room.setState(room.freeState);
}
public void checkIn() {
System.out.println("提供手机号和身份证,成功入住");
room.setState(room.checkedInState);
}
public void checkOut() {
System.out.println("房间尚未入住,无需操作");
}
}
package state;
public class CheckedInState extends RoomState {
public CheckedInState(RoomContext room) {
this.room = room;
}
public void reservation() {
System.out.println("房间已经入住,无需操作");
}
public void cancel() {
System.out.println("房间已经入住,无需操作");
}
public void checkIn() {
System.out.println("房间已经入住,无需操作");
}
public void checkOut() {
System.out.println("成功退房");
room.setState(room.freeState);
}
}
package state;
public class RoomContext {
private RoomState state;
RoomState freeState = new FreeState(this);
RoomState bookedState = new BookedState(this);
RoomState checkedInState = new CheckedInState(this);
public RoomContext() {
this.state = freeState;
}
public void setState(RoomState state) {
this.state = state;
}
public void reservation() {
state.reservation();
}
public void cancel() {
state.cancel();
}
public void checkIn() {
state.checkIn();
}
public void checkOut() {
state.checkOut();
}
}
package state;
public class Client {
public static void main(String[] args) {
RoomContext room = new RoomContext();
room.reservation();
room.checkIn();
room.checkIn();
room.cancel();
room.checkOut();
}
}
输出:
提供手机号,预定成功
提供手机号和身份证,成功入住
房间已经入住,无需操作
房间已经入住,无需操作
成功退房
开发中常见的场景
- 银行系统中账号状态的管理
- OA系统中公文状态的管理
- 酒店系统中,房间状态的管理
- 线程对象各状态之间的切换
好处
- 将与特定状态相关的行为局部化,并且将不同的行为分割开来。
将特定状态相关的行为都放入一个对象中,由于所有状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。 - 状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互的依赖。
什么时候考虑使用状态模式
- 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
网友评论