background
In a project, the user has the function of placing an order, and in different states there are different events to carry out different processing and order state flow. If we only use if else to code, the code readability, extensibility and maintainability will become very poor, so we use state mode to code and design.
The flow of order status
Analysis requires classes and interfaces
First, to clarify the concept, because different order states may have different operations, we call these order operations order events, so we need an order event interface. Then, different order states correspond to different processing, so we need an abstract class for the order and a concrete order implementation class. The same event processing is the same, we can deal with things in the same processor to deal with, easy maintenance. Some context contexts are also included to facilitate parameter extension and passing above. To sum up, we need to have an overview of classes and interfaces
- Order event interface
- Abstract state class
- Different state concrete implementation classes
- The context context
- A concrete event handler class
- The service call
Concrete code implementation
State abstraction class
/ * * *@author: zyb
*/
public class AbstractOrderStatus implements OrderEvent {
@Override
public void orderTimeout(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void paySuccess(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void startServe(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void serverTimeEnd(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void serverExpire(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void finishOrder(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void autoFinishOrder(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void applyRefund(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void approveRefund(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void refuseRefund(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void canceledOrder(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void comment(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow");
}
@Override
public void autoComment(OrderStatusContext context) {
throw new ServiceErrorException("The current order status does not support this flow"); }}Copy the code
Concrete state
Two state concrete implementation classes are briefly listed here
In-service state
/ * * *@author: zyb
*/
@Component("IN_SERVICE")
public class InServiceStatus extends AbstractOrderStatus {
@Autowired
private OrderEventHandel orderEventHandel;
@Override
public void serverTimeEnd(OrderStatusContext context) {
orderEventHandel.serverTimeEnd(context);
}
@Override
public void serverExpire(OrderStatusContext context) {
orderEventHandel.serverExpire(context);
}
@Override
public void finishOrder(OrderStatusContext context) {
orderEventHandel.finishOrder(context);
}
@Override
public void applyRefund(OrderStatusContext context) { orderEventHandel.applyRefund(context); }}Copy the code
Pending payment status
/ * * *@author: zyb
*/
@Component("WAIT_SERVICE")
public class WaitServiceStatus extends AbstractOrderStatus {
@Autowired
private OrderEventHandel orderEventHandel;
@Override
public void startServe(OrderStatusContext context) {
orderEventHandel.startServe(context);
}
@Override
public void finishOrder(OrderStatusContext context) {
orderEventHandel.finishOrder(context);
}
@Override
public void applyRefund(OrderStatusContext context) { orderEventHandel.applyRefund(context); }}Copy the code
Order event interface
/ * * *@author: zyb
*/
public interface OrderEvent {
/**
* 订单超时
*/
void orderTimeout(OrderStatusContext context);
/** * Paid successfully */
void paySuccess(OrderStatusContext context);
/** * Start service */
void startServe(OrderStatusContext context);
/** * Service time ends */
void serverTimeEnd(OrderStatusContext context);
/** * Service expired */
void serverExpire(OrderStatusContext context);
/** * complete the order */
void finishOrder(OrderStatusContext context);
/** * Automatically complete the order */
void autoFinishOrder(OrderStatusContext context);
/** * Apply for a refund */
void applyRefund(OrderStatusContext context);
/** * Agree to refund */
void approveRefund(OrderStatusContext context);
/** * No refund */
void refuseRefund(OrderStatusContext context);
/** * Cancel the order */
void canceledOrder(OrderStatusContext context);
/** * evaluation */
void comment(OrderStatusContext context);
/** * automatic evaluation */
void autoComment(OrderStatusContext context);
}
Copy the code
Event Handler
/ * * *@author: zyb
*/
@Component
@Transactional
public class OrderEventHandel implements OrderEvent {
@Override
public void orderTimeout(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void paySuccess(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void startServe(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void serverTimeEnd(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void serverExpire(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void finishOrder(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void autoFinishOrder(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void applyRefund(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void approveRefund(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void refuseRefund(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void canceledOrder(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void comment(OrderStatusContext context) {
// TODO:Concrete processing logic
}
@Override
public void autoComment(OrderStatusContext context) {
// TODO:Concrete processing logic}}Copy the code
context
/ * * *@author: zyb
*/
@Data
public class OrderStatusContext {
private AbstractOrderStatus orderStatus;
private String orderEvent;
private Long orderId;
private OrderEventParam orderEventParam;
public OrderStatusContext(AbstractOrderStatus orderStatus, String orderEvent, Long orderId, OrderEventParam orderEventParam) {
this.orderStatus = orderStatus;
this.orderEvent = orderEvent;
this.orderId = orderId;
this.orderEventParam = orderEventParam;
}
public Boolean doAction(a) {
switch (orderEvent) {
case OrderConstant.APPLY_REFUND:
orderStatus.applyRefund(this);
break;
case OrderConstant.APPROVE_REFUND:
orderStatus.approveRefund(this);
break;
case OrderConstant.CANCELED_ORDER:
orderStatus.canceledOrder(this);
break;
case OrderConstant.FINISH_ORDER:
orderStatus.finishOrder(this);
break;
case OrderConstant.AUTO_FINISH_ORDER:
orderStatus.autoFinishOrder(this);
break;
case OrderConstant.ORDER_TIMEOUT:
orderStatus.orderTimeout(this);
break;
case OrderConstant.PAY_SUCCESS:
orderStatus.paySuccess(this);
break;
case OrderConstant.REFUSE_REFUND:
orderStatus.refuseRefund(this);
break;
case OrderConstant.SERVER_TIME_EDN:
orderStatus.serverTimeEnd(this);
break;
case OrderConstant.START_SERVE:
orderStatus.startServe(this);
break;
case OrderConstant.COMMENT:
orderStatus.comment(this);
break;
case OrderConstant.AUTO_COMMENT:
orderStatus.autoComment(this);
break;
default:
throw new ServiceErrorException("This event is not supported at this time");
}
return true; }}Copy the code
The service layer calls
public boolean orderEvent(Long id, String orderEvent, OrderEventParam orderEventParam) {
OrderInfoEntity orderInfoEntity = orderInfoMapper.selectById(id);
AbstractOrderStatus orderStatus = (AbstractOrderStatus) SpringContextUtils.getBean(orderInfoEntity.getOrderStatus());
OrderStatusContext context = new OrderStatusContext(orderStatus, orderEvent, id, orderEventParam);
context.doAction();
return true;
}
Copy the code
Other implementations
In Spring framework projects, developers can obtain a business state machine through simple configuration, without having to manage state machine definition, initialization, and so on. Interested students can also go to learn.
conclusion
In complex business scenarios, the rational use of design patterns can greatly improve the maintainability, readability and expansibility of our code. Any mistakes can be pointed out, welcome to discuss.