聊聊状态模式
介绍
状态模式(State Pattern),允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
它的用途,可以用来根据状态来支持相对应的操作。举个例子,比如,一个非常简单的订单(不涉及支付)场景。
它有三种状态:
- 待接单(当用户下单后,就通知服务人员接单)
- 进行中(当服务人员接单后,该订单显示进行中)
- 已完成(订单完成后,服务人员手动关闭订单,该订单就完成了)
示例
好了,我们直接根据上面定义的状态来写一个示例:
// 服务订单类
public class ServiceOrder {
/**
* 待接单状态
*/
final int WAITING = 0;
/**
* 进行中状态
*/
final int ONGOING = 1;
/**
* 已完成状态
*/
final int COMPLETED = 2;
private final String order;
/**
* 默认待接单状态
*/
int state = WAITING;
public ServiceOrder(String order) {
this.order = order;
print();
}
public void serviceReceiving(String order) {
System.out.println("服务人员已接单:" + order);
state = ONGOING;
print();
}
public void completedOrder(String order) {
System.out.println("服务人员已完成该订单:" + order);
state = COMPLETED;
print();
}
public void print() {
System.out.println("正在查询订单状态:");
if (state == WAITING) {
System.out.println("接收到新的订单:" + order);
System.out.println("正在通知服务人员接单!");
serviceReceiving(order);
} else if (state == ONGOING) {
System.out.println("订单进行中!");
} else if (state == COMPLETED) {
System.out.println("订单已完成!");
}
}
}
然后,再写个测试用例测试一下:
public static void main(String[] args) throws InterruptedException {
String order = "\n====\n服务:远程修BUG\n价格:500¥\n====\n";
ServiceOrder serviceOrder = new ServiceOrder(order);
// 服务人员已完成订单
serviceOrder.completedOrder(order);
}
输出结果如下:
正在查询订单状态:
接收到新的订单:
====
服务:远程修BUG
价格:500¥
====
正在通知服务人员接单!
服务人员已接单:
====
服务:远程修BUG
价格:500¥
====
正在查询订单状态:
订单进行中!
服务人员已完成该订单:
====
服务:远程修BUG
价格:500¥
====
正在查询订单状态:
订单已完成!
这个就是一个订单状态更变时的一个例子。不过代码中的IF ELSE 不是很好维护,缺乏灵活性。
不过,我们可以用状态模式来改进它。
// 状态接口
public interface OrderState {
void serviceReceiving(String order);
void completedOrder(String order);
void print();
}
// 待接单
public class WaitingState implements OrderState {
private final ServiceOrder serviceOrder;
public WaitingState(ServiceOrder serviceOrder) {
this.serviceOrder = serviceOrder;
}
@Override
public void serviceReceiving(String order) {
System.out.println("服务人员已接单:" + order);
// 扭转状态
serviceOrder.setState(serviceOrder.getOngoingState());
}
@Override
public void completedOrder(String order) {
System.out.println("该状态不支持当前操作!");
}
@Override
public void print() {
System.out.println("正在通知服务人员接单!");
}
}
// 进行中
public class OnGoingState implements OrderState {
private ServiceOrder serviceOrder;
public OnGoingState(ServiceOrder serviceOrder) {
this.serviceOrder = serviceOrder;
}
@Override
public void serviceReceiving(String order) {
System.out.println("该状态不支持当前操作!");
}
@Override
public void completedOrder(String order) {
// 扭转状态
serviceOrder.setState(serviceOrder.getCompletedState());
}
@Override
public void print() {
System.out.println("订单正在进行中!");
}
}
// 已完成
public class CompletedState implements OrderState {
private final ServiceOrder serviceOrder;
public CompletedState(ServiceOrder serviceOrder) {
this.serviceOrder = serviceOrder;
}
@Override
public void serviceReceiving(String order) {
System.out.println("该状态不支持当前操作!");
}
@Override
public void completedOrder(String order) {
// 已完成
}
@Override
public void print() {
System.out.println("该订单已完成!");
}
}
// 服务订单类
public class ServiceOrder {
private final OrderState waitingState;
private final OrderState ongoingState;
private final OrderState completedState;
private final String order;
private OrderState state;
public ServiceOrder(String order) {
this.waitingState = new WaitingState(this);
this.ongoingState = new OnGoingState(this);
this.completedState = new CompletedState(this);
this.order = order;
this.state = this.getWaitingState();
this.print();
}
public OrderState getWaitingState() {
return waitingState;
}
public OrderState getOngoingState() {
return ongoingState;
}
public OrderState getCompletedState() {
return completedState;
}
public void setState(OrderState state) {
this.state = state;
}
public void serviceReceiving() {
state.serviceReceiving(order);
print();
}
public void completedOrder() {
state.completedOrder(order);
print();
}
public void print() {
state.print();
}
}
// 测试
public static void main(String[] args) throws InterruptedException {
String order = "\n====\n服务:远程修BUG\n价格:500¥\n====\n";
ServiceOrder serviceOrder = new ServiceOrder(order);
// 订单进行中...
serviceOrder.serviceReceiving();
// 服务人员已完成订单
serviceOrder.completedOrder();
}
这样,我们就使用状态模式将它更改完了。
比起IF ELSE来说更加灵活,之后再新增状态也方便,而不是通过IF ELSE来判断。
不过一值得一提的是,状态模式可能跟策略模式很类似,但它们的"意图"却是不相同的。