状态模式
状态模式(State Pattern):又称为状态机模式(State Machine Pattern),是允许对象在内部状态发生改变的同时改变对象的行为,使得看起来像是修改了类一样,其核心就是给每一种状态绑定一种行为。
状态模式中的类的行为是由状态决定的,不同的状态有不同的行为。状态模式的意图是让一个对象在其内部改变时行为也随之一起改变。
示例:我们通过订单状态(待支付,待收货,已收货)的流转来举例说明...
package cn.liangyy.state;
/**
* 抽象的订单状态类
*/
public abstract class AbstractOrderState {
//订单上下文,用来负责状态切换
protected OrderContext orderContext;
public AbstractOrderState(OrderContext orderContext) {
this.orderContext = orderContext;
}
/**
* 待支付状态订单对应行为:支付
*/
public abstract void payOrder();
/**
* 已支付状态订单对应行为:发货
*/
public abstract void deliver();
/**
* 已收货状态订单对应行为:收货
*/
public abstract void receiveGoods();
}
复制代码
package cn.liangyy.state;
/**
* 待支付状态类
*/
public class WaitPaidOrderState extends AbstractOrderState {
public WaitPaidOrderState(OrderContext orderContext) {
super(orderContext);
}
/**
* 待支付状态绑定支付行为
*/
@Override
public void payOrder() {
System.out.println("支付成功!");
//切换状态
this.orderContext.setState(this.orderContext.waitDeliver);
}
/**
* 不是待支付状态订单的行为
*/
@Override
public void deliver() {
System.out.println("对不起,请先支付!");
}
/**
* 不是待支付状态订单的行为
*/
@Override
public void receiveGoods() {
System.out.println("对不起,请先支付!");
}
}
复制代码
package cn.liangyy.state;
/**
* 代发货状态类
*/
public class WaitDeliverOrderState extends AbstractOrderState {
public WaitDeliverOrderState(OrderContext orderContext) {
super(orderContext);
}
/**
* 不是代发货状态订单的行为
*/
@Override
public void payOrder() {
System.out.println("你已经支付过了!");
}
@Override
public void deliver() {
System.out.println("商品已发货并送达!");
//切换状态
this.orderContext.setState(this.orderContext.receiveGoods);
}
/**
* 不是代发货状态订单的行为
*/
@Override
public void receiveGoods() {
System.out.println("请不要着急,商品即将发货!");
}
}
复制代码
package cn.liangyy.state;
/**
* 待收货状态类
*/
public class ReceiveGoodsOrderState extends AbstractOrderState {
public ReceiveGoodsOrderState(OrderContext orderContext) {
super(orderContext);
}
/**
* 不是待收货状态订单的行为
*/
@Override
public void payOrder() {
System.out.println("你已经支付过了,请不要重复支付!");
}
/**
* 不是待收货状态订单的行为
*/
@Override
public void deliver() {
System.out.println("商品已发货并送达,请不要重复发货!");
}
@Override
public void receiveGoods() {
System.out.println("用户已收到商品,此次交易结束!");
}
}
复制代码
package cn.liangyy.state;
/**
* 订单上下文类
*/
public class OrderContext {
//待支付状态
AbstractOrderState waitPaid;
//代发货状态
AbstractOrderState waitDeliver;
//待收货状态
AbstractOrderState receiveGoods;
//当前状态
AbstractOrderState currState;
public OrderContext() {
//初始化 待支付 状态订单
this.waitPaid = new WaitPaidOrderState(this);
//初始化 待发货 状态订单
this.waitDeliver = new WaitDeliverOrderState(this);
//初始化 待收货 状态订单
this.receiveGoods = new ReceiveGoodsOrderState(this);
//当前状态,默认待支付
currState = waitPaid;
}
void setState(AbstractOrderState state){
this.currState = state;
}
//支付
public void payOrder(){
currState.payOrder();
}
//发货
public void deliver(){
currState.deliver();
}
//收货
public void receiveGoods(){
currState.receiveGoods();
}
}
复制代码
package cn.liangyy.state;
/**
* 状态模式-测试
*/
public class TestState {
public static void main(String[] args) {
//创建订单上下文,默认待支付状态
OrderContext orderContext = new OrderContext();
//支付,支付完成之后状态自动切换到待发货
orderContext.payOrder();
//发货,发货完成之后状态自动切换到待收货
orderContext.deliver();
//收货
orderContext.receiveGoods();
}
}
复制代码
上述例子就是一个状态的全部流程,看起来是一个状态一个状态的往下执行,有点类似责任链模式,但是这两种模式肯定是不等价的。
状态模式和责任链模式状态模式、责任链模式都是一条链去处理,可以这么说在某种场景下这两种模式可以互相替换,但是这两种模式也是有本质区别的:
状态模式和策略模式状态模式和策略模式都能用来消除大量的 if/else 场景,但是也有本质区别:
状态模式适用场景当控制一个对象状态的条件表达式过于复杂的时候,就可以考虑使用状态模式,通过把状态的判断逻辑转移到表示不同状态的一系列类中,这样就可以把复杂的逻辑简单化,使得对象的行为依赖于它的状态,并且会随着状态的改变而同时改变行为。
状态模式优点
状态模式缺点
评论