状态模式
- 定义
状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类,属于行为型模式
- 状态模式类图
- 环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
- 抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
- 具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
- 状态模式例子
我们通常购物的时候,我们会先下订单,这个时候订单的状态就是待付款状态,这个时候我们可以去付款,付完款了,订单的状态就是待发货状态,这个时候订单可以去发货,商家发货了,这个时候订单的状态就是运送中,这个时候我们可以去收货,当我们确认收货了,订单的状态变成待评价状态,这个时候我们可以去评价订单,现在我们来用状态模式完成这个流程
先定义状态接口,里面有几个方法
public interface OrderState {
// 付款
public void pay();
// 发货
public void deliver();
// 收货
public void takeDeliver();
// 评价
public void appraise();
}
//类分割
public class AbstractOrderState implements OrderState {
protected Order order;
public AbstractOrderState(Order order) {
this.order = order;
}
@Override
public void pay() {
throw new RuntimeException("方法未定义");
}
@Override
public void deliver() {
throw new RuntimeException("方法未定义");
}
@Override
public void takeDeliver() {
throw new RuntimeException("方法未定义");
}
@Override
public void appraise() {
throw new RuntimeException("方法未定义");
}
}
具体的状态类
待付款状态
public class ObligationState extends AbstractOrderState{
public ObligationState(Order order) {
super(order);
}
@Override
public void pay() {
System.out.println("用户付款了");
// 把订单的状态变成待发货状态
order.setCurrentState(Order.deliverState);
}
}
待发货状态
public class DeliverState extends AbstractOrderState {
public DeliverState(Order order) {
super(order);
}
@Override
public void deliver() {
System.out.println("订单已发货");
order.setCurrentState(Order.shipState);
}
}
运送中状态
public class ShipState extends AbstractOrderState {
public ShipState(Order order) {
super(order);
}
@Override
public void takeDeliver() {
System.out.println("用户确认收货");
order.setCurrentState(Order.receivedState);
}
}
已收货状态
public class ReceivedState extends AbstractOrderState {
public ReceivedState(Order order) {
super(order);
}
@Override
public void appraise() {
System.out.println("用户已评价");
}
}
订单类
public class Order {
public static OrderState obligationState;
public static OrderState deliverState;
public static OrderState receivedState;
public static OrderState shipState;
public Order() {
obligationState = new ObligationState(this);
deliverState = new DeliverState(this);
receivedState = new ReceivedState(this);
shipState = new ShipState(this);
}
private OrderState currentState;
public OrderState getCurrentState() {
return currentState;
}
public void setCurrentState(OrderState currentState) {
this.currentState = currentState;
}
public void handle() {
setCurrentState(Order.obligationState);
currentState.pay();
currentState.deliver();
currentState.takeDeliver();
currentState.appraise();
}
}
测试
public class MyClient {
public static void main(String[] args) {
Order order = new Order();
order.handle();
}
}
运行结果
用户付款了
订单已发货
用户确认收货
用户已评价
状态和行为:
所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。
状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。也就是说,状态和行为是相关联的,它们的关系可以描述为:状态决定行为 。
由于状态是在运行期被改变的,因此行为也会在运行期根据状态的改变而改变。
- 总结
- 在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。
- 在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类
- 客户端一般只和环境(Context)交互。客户端可以用状态对象来配置一个环境(Context),一旦配置完毕,就不再需要和状态对象打交道了。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。