背景
假设要做个电梯控制系统。电梯可以处于不同的状态:
- 已开门:只能关门操作
- 已关门:可以开门,可以上升,可以下降
- 开门中:不可做任何操作
- 关门中:不可做任何操作
- 上升中:不可做任何操作
- 下降中:不可做任何操作
这时可以使用状态模式。
概述
状态模式是一种行为设计模式,它可以让对象在内部状态改变时改变它的行为。简而言之,状态模式允许对象在不同状态下更改其行为,而不需要通过使用大量的条件语句进行手动更改。
示例一
以电梯为例
public class Elevator {
private ElevatorState state;
public Elevator() {
this.state = new ClosedState(this);
}
public void setState(ElevatorState state) {
this.state = state;
}
public void openDoors() {
state.openDoors();
}
public void closeDoors() {
state.closeDoors();
}
public void goUp() {
state.goUp();
}
public void goDown() {
state.goDown();
}
}
public abstract class ElevatorState {
protected Elevator elevator;
public ElevatorState(Elevator elevator) {
this.elevator = elevator;
}
abstract void openDoors();
abstract void closeDoors();
abstract void goUp();
abstract void goDown();
}
public class OpenState extends ElevatorState {
public OpenState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("已经开门");
}
@Override
void closeDoors() {
System.out.println("正在关门");
elevator.setState(new ClosingState(elevator));
}
@Override
void goUp() {
System.out.println("无法上升,先关门");
}
@Override
void goDown() {
System.out.println("无法下降,先关门");
}
}
public class ClosedState extends ElevatorState {
public ClosedState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("正在开门");
elevator.setState(new OpeningState(elevator));
}
@Override
void closeDoors() {
System.out.println("已经关门");
}
@Override
void goUp() {
System.out.println("正在上升");
elevator.setState(new GoingUpState(elevator));
}
@Override
void goDown() {
System.out.println("正在下降");
elevator.setState(new GoingDownState(elevator));
}
}
public class OpeningState extends ElevatorState {
public OpeningState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("正在开门中,无法操作");
}
@Override
void closeDoors() {
System.out.println("正在开门中,无法操作");
}
@Override
void goUp() {
System.out.println("正在开门中,无法操作");
}
@Override
void goDown() {
System.out.println("正在开门中,无法操作");
}
}
public class ClosingState extends ElevatorState {
public ClosingState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("正在关门中,无法操作");
}
@Override
void closeDoors() {
System.out.println("正在关门中,无法操作");
}
@Override
void goUp() {
System.out.println("正在关门中,无法操作");
}
@Override
void goDown() {
System.out.println("正在关门中,无法操作");
}
}
public class GoingUpState extends ElevatorState {
public GoingUpState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("无法开门,先停止上升");
}
@Override
void closeDoors() {
System.out.println("无法关门,先停止上升");
}
@Override
void goUp() {
System.out.println("正在上升中");
}
@Override
void goDown() {
System.out.println("无法下降,先停止上升");
}
}
public class GoingDownState extends ElevatorState {
public GoingDownState(Elevator elevator) {
super(elevator);
}
@Override
void openDoors() {
System.out.println("无法开门,先停止下降");
}
@Override
void closeDoors() {
System.out.println("无法关门,先停止下降");
}
@Override
void goUp() {
System.out.println("无法上升,先停止下降");
}
@Override
void goDown() {
System.out.println("正在下降中");
}
}
测试
public class Main {
public static void main(String[] args) {
Elevator elevator = new Elevator();
// 测试关门状态
elevator.setState(new DoorsClosedState(elevator)); // 设置为关门状态
elevator.openDoors(); // 正在开门
elevator.setState(new DoorsClosedState(elevator)); // 设置为关门状态
elevator.closeDoors(); // 已经关门
elevator.setState(new DoorsClosedState(elevator)); // 设置为关门状态
elevator.goUp(); // 正在上升
elevator.setState(new DoorsClosedState(elevator)); // 设置为关门状态
elevator.goDown(); // 正在下降
// 测试开门状态
elevator.setState(new DoorsOpenedState(elevator)); // 设置为开门状态
elevator.openDoors(); // 已经开门
elevator.setState(new DoorsOpenedState(elevator)); // 设置为开门状态
elevator.closeDoors(); // 正在关门
elevator.setState(new DoorsOpenedState(elevator)); // 设置为开门状态
elevator.goUp(); // 无法上升,先关门
elevator.setState(new DoorsOpenedState(elevator)); // 设置为开门状态
elevator.goDown(); // 无法下降,先关门
}
}
示例二
假设我们正在开发一个电子商务平台,需要实现订单状态的管理。订单的状态可以有多种,例如待支付、已支付、已发货、已完成等。不同的状态下,订单的行为也不同。
首先,我们定义订单状态接口OrderState
,并在接口中定义订单的行为:
public interface OrderState {
void pay(Order order);
void deliver(Order order);
void complete(Order order);
}
然后,我们实现具体的订单状态类,例如待支付状态PendingPaymentState
、已支付状态PaidState
、已发货状态ShippedState
和已完成状态CompletedState
:
public class PendingPaymentState implements OrderState {
@Override
public void pay(Order order) {
System.out.println("订单已支付");
order.setState(new PaidState());
}
@Override
public void deliver(Order order) {
System.out.println("订单未支付,不能发货");
}
@Override
public void complete(Order order) {
System.out.println("订单未支付,不能完成");
}
}
public class PaidState implements OrderState {
@Override
public void pay(Order order) {
System.out.println("订单已支付");
}
@Override
public void deliver(Order order) {
System.out.println("订单已发货");
order.setState(new ShippedState());
}
@Override
public void complete(Order order) {
System.out.println("订单未发货,不能完成");
}
}
public class ShippedState implements OrderState {
@Override
public void pay(Order order) {
System.out.println("订单已支付");
}
@Override
public void deliver(Order order) {
System.out.println("订单已发货");
}
@Override
public void complete(Order order) {
System.out.println("订单已完成");
order.setState(new CompletedState());
}
}
public class CompletedState implements OrderState {
@Override
public void pay(Order order) {
System.out.println("订单已支付,不能重新支付");
}
@Override
public void deliver(Order order) {
System.out.println("订单已完成,不能发货");
}
@Override
public void complete(Order order) {
System.out.println("订单已完成");
}
}
接下来,我们定义订单类Order
,并在类中保存订单的状态和执行订单相关的行为:
public class Order {
private OrderState state;
public Order() {
this.state = new PendingPaymentState();
}
public void setState(OrderState state) {
this.state = state;
}
public void pay() {
state.pay(this);
}
public void deliver() {
state.deliver(this);
}
public void complete() {
state.complete(this);
}
}
现在,我们可以创建订单对象,并根据不同的状态执行订单的行为:
public class StateExample {
public static void main(String[] args) {
// 创建订单对象
Order order = new Order();
// 执行订单的行为
order.pay();
order.deliver();
order.complete();
}
}
运行结果
订单已支付
订单未支付,不能发货
订单未支付,不能完成