设计模式之 状态模式
一、定义
状态模式:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
二、分析
状态模式把不同的状态封装成类,并将对应的动作委托到对应的类中,只要状态一改变,对应的动作与会随之改变。
状态模式主要应用于业务逻辑中包含大量的状态判断的条件语句。我们可以把各个状态抽象出来,然后实现和各个状态相关的业务操作。
状态模式的优点在于:
- 封装了转换的规则:改变状态的方法放在具体状态类中切换;
- 把状态和状态有关的行为放在一个类中,便于添加新的状态;只需要编写新的状态,然后切换到这个状态即可。
三、类图
下面是状态模式的类图:
四、代码实现
我们使用代码来实现状态模式:
源码:gitee
项目结构如下:
1.抽象状态类 OrderState.java
package state;
/**
* 订单状态抽象
*
* @author lixin
*/
public interface OrderState {
/**
* 查询订单的详细信息
*
* @param context 订单查询类
* @param orderId 订单ID
* @return 订单详情实体
*/
OrderDetail findOrderDetail(OrderDetailContext context, Long orderId);
}
2.创建数据实体 OrderDetail.java
package state;
/**
* 订单详情实体
*
* @author lixin
*/
public class OrderDetail {
private Long id;
private String name;
private String orderNo;
private Integer status;
public OrderDetail(Long id, String name, String orderNo, Integer status) {
this.id = id;
this.name = name;
this.orderNo = orderNo;
this.status = status;
}
@Override
public String toString() {
return "OrderDetail{" +
"id=" + id +
", name='" + name + '\'' +
", orderNo='" + orderNo + '\'' +
", status=" + status +
'}';
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
3.实现具体状态的操作逻辑 PayIngState.java PayCompleteState.java OrderExpireState.java
// PayIngState.java
package state.impl;
import state.OrderDetail;
import state.OrderDetailContext;
import state.OrderState;
/**
* 订单支付中
*
* @author lixin
*/
public class PayIngState implements OrderState {
@Override
public OrderDetail findOrderDetail(OrderDetailContext context, Long orderId) {
context.setOrderState(this);
System.out.println("订单支付中...");
OrderDetail orderDetail = findBiId(orderId);
updateOrderState(orderDetail.getOrderNo());
return findBiId(orderId);
}
/**
* 到微信上查询订单是否交易完成
* 如果完成就更新一下订单得到的状态
*
* @param orderNo 订单号
*/
private void updateOrderState(String orderNo) {
System.out.println("根据订单号到微信支付同步订单状态...");
}
/**
* 根据订单ID查询订单信息
*
* @param orderId 订单ID
* @return 订单信息
*/
private OrderDetail findBiId(Long orderId) {
System.out.println(String.format("根据orderId=%d查询到订单信息...", orderId));
return new OrderDetail(1L, "手续费", "ZM2021021016560458", 0);
}
}
// PayCompleteState.java
package state.impl;
import state.OrderDetail;
import state.OrderDetailContext;
import state.OrderState;
/**
* 订单支付完成
*
* @author lixin
*/
public class PayCompleteState implements OrderState {
@Override
public OrderDetail findOrderDetail(OrderDetailContext context, Long orderId) {
context.setOrderState(this);
System.out.println("订单支付完成...");
return findBiId(orderId);
}
/**
* 根据订单ID查询订单信息
*
* @param orderId 订单ID
* @return 订单信息
*/
private OrderDetail findBiId(Long orderId) {
System.out.println(String.format("根据orderId=%d到完成的订单表中查询记录的信息...", orderId));
return new OrderDetail(2L, "套餐3费用", "ZM2021021016562514", 1);
}
}
// OrderExpireState.java
package state.impl;
import state.OrderDetail;
import state.OrderDetailContext;
import state.OrderState;
/**
* 订单过期
*
* @author lixin
*/
public class OrderExpireState implements OrderState {
@Override
public OrderDetail findOrderDetail(OrderDetailContext context, Long orderId) {
context.setOrderState(this);
System.out.println("订单过期...");
return findBiId(orderId);
}
/**
* 根据订单ID查询订单信息
*
* @param orderId 订单ID
* @return 订单信息
*/
private OrderDetail findBiId(Long orderId) {
System.out.println(String.format("根据orderId=%d到过期订单表中查询信息...", orderId));
return new OrderDetail(3L, "套餐99费用", "ZM2021021016560345", -1);
}
}
4.创建使用状态的类 OrderDetailContext.java
package state;
/**
* 订单操作类
*
* @author lixin
*/
public class OrderDetailContext {
private OrderState orderState;
public OrderDetailContext() {
}
public OrderState getOrderState() {
return orderState;
}
public void setOrderState(OrderState orderState) {
this.orderState = orderState;
}
/**
* 查询订单详情
*
* @param orderId 订单ID
* @return 订单详情
*/
public OrderDetail findOrderDetail(Long orderId) {
return orderState.findOrderDetail(this, orderId);
}
}
5.创建测试类
package state;
import state.impl.OrderExpireState;
import state.impl.PayCompleteState;
import state.impl.PayIngState;
/**
* 状态模式测试类
*
* @author lixin
*/
public class StateDemoMain {
public static void main(String[] args) {
// 创建Context使用状态
OrderDetailContext context = new OrderDetailContext();
// 改变状态
context.setOrderState(new PayIngState());
// 执行对应状态的处理方法
OrderDetail detail1 = context.findOrderDetail(1L);
System.out.println(detail1);
System.out.println("==================");
// 切换到另外一个状态
context.setOrderState(new PayCompleteState());
// 执行对应状态的处理方法
OrderDetail detail2 = context.findOrderDetail(2L);
System.out.println(detail2);
System.out.println("==================");
// 切换到另外一个状态
context.setOrderState(new OrderExpireState());
// 执行对应状态的处理方法
OrderDetail detail3 = context.findOrderDetail(3L);
System.out.println(detail3);
}
}
/* 输出结果:
订单支付中...
根据orderId=1查询到订单信息...
根据订单号到微信支付同步订单状态...
根据orderId=1查询到订单信息...
OrderDetail{id=1, name='手续费', orderNo='ZM2021021016560458', status=0}
==================
订单支付完成...
根据orderId=2到完成的订单表中查询记录的信息...
OrderDetail{id=2, name='套餐3费用', orderNo='ZM2021021016562514', status=1}
==================
订单过期...
根据orderId=3到过期订单表中查询信息...
OrderDetail{id=3, name='套餐99费用', orderNo='ZM2021021016560345', status=-1}
*/
原创内容,如果你觉得文章还可以的话,不妨点个赞支持一下!转载请注明出处。