早之前就研究过老大开发的订单框架,一直想把它的最核心部分用到的设计模式放到最后面来写,作为本系列博客的收官之作。这段时间决定把部门框架的演进之路作为一个系列的博客写出来,而新框架最核心的部分就是订单,在我们的金融系统里面,所有的业务请求,都被视为一笔订单。而订单的核心代码,其实就是一个状态机的实现,下面就让我以我们部门的订单状态机为例子,阐述下我对设计模式中状态模式的理解,仅供大家交流学习。
什么是状态模式?
状态模式是指对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类,实际是转换到了另一个实现
使用场景
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);
}
各个状态的执行器我就不每个都贴出来了,这里只贴一个Init状态的执行器:
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:");
}
}
bean文件配置:
<?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>