早之前就研究过老大开发的订单框架,一直想把它的最核心部分用到的设计模式放到最后面来写,作为本系列博客的收官之作。这段时间决定把部门框架的演进之路作为一个系列的博客写出来,而新框架最核心的部分就是订单,在我们的金融系统里面,所有的业务请求,都被视为一笔订单。而订单的核心代码,其实就是一个状态机的实现,下面就让我以我们部门的订单状态机为例子,阐述下我对设计模式中状态模式的理解,仅供大家交流学习。
什么是状态模式?
状态模式是指对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类,实际是转换到了另一个实现
使用场景
1. 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为;
2. 一个操作中含有庞大的分支结构,并且这些分支决定于对象的装填。
类图(以当前我们的订单框架状态机为例):
订单状态迁移路线如下:
代码结构:
在订单初始化后(将orderState初始化为init状态),进入状态机的循环,每个循环的过程不断通过状态执行器工厂OrderStateHandlerFactory获取到状态的执行器,从而去执行该执行器的execute方法,对应的状态机的循环的代码如下:
package order; import logic.LogicRunner; import logic.LogicType; import orderStateHandler.OrderStateHandler; import orderStateHandler.OrderStateHandlerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import bo.OrderContext; import businessService.BusinessService; import businessService.Impl.AbstractBusinessServiceImpl; /* * 个人业务总入口 */ public abstract class AbstractOrderService extends AbstractBusinessServiceImpl { OrderContext orderContext; @Override public void doIt(BusinessService businessService) { try { this.initOrderState(); boolean IsInterrupt = false; while(IsInterrupt) { OrderStateHandler orderStateHandler = OrderStateHandlerFactory .getOrderStateHandler(businessService.getOrderContext() .getOrder().getOrderState().toString()); IsInterrupt = orderStateHandler.execute(orderContext, businessService); } } catch (Exception e) { // TODO: handle exception } finally { // finally } } private void initOrderState() { // 初始化bean容器 ApplicationContext context = new ClassPathXmlApplicationContext( "Beans.xml"); orderContext.setContext(context); // 初始化上下文 orderContext.getOrder().setOrderState(OrderState.INIT); // 执行初始化logic LogicRunner.ChainExecutor(orderContext.getChainId(), LogicType.INIT); } }
package orderStateHandler; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class OrderStateHandlerFactory { public static OrderStateHandler getOrderStateHandler(String preBeanString) throws Exception { // bean 名字的拼装,拼装规则:前置Bean名字+ServiceConvertor String HandlerBeanName = preBeanString + "OrderStateProcessor"; ApplicationContext context = new ClassPathXmlApplicationContext( "Beans.xml"); // 根据Bean名字,通过spring的IoC去获取实现并返回 OrderStateHandler orderStateHandler = (OrderStateHandler) context .getBean(HandlerBeanName); // 取到哑实现,抛异常处理 if (null == orderStateHandler) { throw new Exception(); } return orderStateHandler; } }
在获取到订单执行器后,接下来就是各个订单执行器之间跳转,以及何时从各个执行器跳转中退出的问题了,为了强制各个状态的执行器都能设置下一个状态的跳转(避免因为程序的实现忘记设置下一个跳转状态,会导致死循环的问题),同时把一些公共的处理都放到父类实现,从而避免代码重复率的问题,这里把模板方法设计模式给使用上了,写一个抽象类AbstractOrderStateHandler,把业务的公共处理都放到这里来,下个状态的设置写成一个抽象方法,这样每个状态去继承该抽象类的时候,就强制实现该抽象方法了:
package orderStateHandler; import bo.OrderContext; import businessService.BusinessService; public abstract class AbstractOrderStateHandler implements OrderStateHandler { // 状态执行器 @Override public boolean execute(OrderContext orderContext,BusinessService businessService) { System.out.println("entering the handleOrderState:"); try { // 各个状态的处理 this.handle(businessService, orderContext); // 设置下个跳转节点 this.setNextState(businessService); } catch (Exception e) { // TODO: handle exception } return orderContext.isInterruptFlow(); } public abstract void handle(BusinessService businessService,OrderContext orderContext); public abstract void setNextState(BusinessService businessService); }
package orderStateHandler; import order.OrderState; import bo.OrderContext; import businessService.BusinessService; public class InitOrderStateProcessor extends AbstractOrderStateHandler { @Override public void handle(BusinessService businessService, OrderContext orderContext) { // TODO Auto-generated method stub System.out.println("Entering the CompleteOrderStateProcessor handle"); businessService.preInit(); createOrder(orderContext); InitialContext(orderContext); orderContext.setInterruptFlow(false); } @Override public void setNextState(BusinessService businessService) { if(!businessService.getOrderContext().isInterruptFlow()) { businessService.getOrderContext().getOrder().setOrderState(OrderState.PROCESS); } } private void createOrder(OrderContext orderContext) { System.out.println("Creating order:"); } private void InitialContext(OrderContext orderContext) { System.out.println("Initing orderContext:"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="InitOrderStateProcessor" class="orderStateHandler.InitOrderStateProcessor"> </bean> </beans>