前言
学习完状态模式之后就派上了用处,最近在公司处理了订单状态更新这个业务。我用一个案例给大家展示状态模式写该业务的优雅!
业务
不同状态的订单都有对应的相关操作,简单举例如下:
状态 | 相关操作 |
未支付 | 支付、取消支付 |
已支付 | 申请退款 |
待发货 | 确认发货 |
待收货 | 签收 |
已签收 | 评论、退货 |
一个完整的物流系统肯定有非常多的状态,且每种状态都有相关的操作可以执行!
如果先是按照这个思路去编写代码:
支付接口 | Action --> Service(实现业务逻辑)--> DAO |
确认收货接口 | Action --> Service(实现业务逻辑) --> DAO |
签收接口 | Action --> Service(实现业务逻辑) --> DAO |
甚至可能是支付接口的service就会有上百行代码...这些接口对应的方法都写在一个类GoodOrderService中?这阅读性和维护性,维护一次看完一本书!
再高类聚一点就可以进行封装,可不可以每个状态都去定义一个类,然后这个状态类专门来管理这个状态对应的操作的业务呢?比如:未支付状态定义为一个类,然后这个类里面专门实现支付和取消支付的业务!
这样我们就可以将所以涉及到“状态”的业务进行分类并且集中管理。然后配合状态模式,如果订单新增了一个状态,或者哪个状态需要更新迭代,我们只需要新增一共类到系统中,不需要再修改原有代码,这样就算出现新问题,也能及时回退。
个人画了一个类图如下:
每个组件可以看作一张订单表,有很多状态变化的表。只需要维护组件即可!
组件详细类图:
枚举
用枚举的状态码code作为key注册到Context上下文容器中。GoodOrderAction枚举是一个行为枚举,由后台将枚举由Controller层最终传输到对应的Handler处理器中,然后用传过来的行为枚举和当前Handler对应的行为枚举是否相同,不相同则表示当前订单状态不能由该状态处理器处理。
枚举状态码就对应着订单的状态,执行操作之前,先读取数据库验证数据真实性,然后再用读取到的订单对象的状态属性从上下文中获取handler然后执行业务。
行为枚举是用来防御别人修改了请求数据导致不该发货的订单执行了发货逻辑,导致系统bug!
代码的话可以自学学习状态模式,然后参照类图进行编写。整体一个架构。