唐山哪里有建设网站的seo群发软件
- 作者: 五速梦信息网
- 时间: 2026年03月21日 08:23
当前位置: 首页 > news >正文
唐山哪里有建设网站的,seo群发软件,怎么制作网站域名,宁波高端网站建设推广文章目录 1. 前言2.状态模式2.1.订单状态流转案例2.1.1.状态枚举定义2.1.2.状态接口与实现2.1.3.状态机2.1.4.测试 2.2.退款状态的拓展2.2.1.代码拓展2.2.2.测试 2.3.小结 3.总结 1. 前言
状态模式一般是用在对象内部的状态流转场景中#xff0c;用来实现状态机。
什么是状态… 文章目录 1. 前言2.状态模式2.1.订单状态流转案例2.1.1.状态枚举定义2.1.2.状态接口与实现2.1.3.状态机2.1.4.测试 2.2.退款状态的拓展2.2.1.代码拓展2.2.2.测试 2.3.小结 3.总结 1. 前言
状态模式一般是用在对象内部的状态流转场景中用来实现状态机。
什么是状态机呢 状态机是对状态转移的抽象由事件、状态、动作组成事件有时候也被称为转移事件或者转移当事件触发时可以将状态由一个状态变更为另一个状态并执行动作。其中事件和状态是必须存在的动作可以不要。
下面是一张状态图表达的就是一个状态机的模型。 通俗来讲就是对状态的变更做了一定的限制不能随意的修改状态而是只有处于某个特定的状态时才能变更到另一个特定的状态。
2.状态模式
状态模式将状态抽象成一个个的状态对象状态机当前持有某个状态对象就表示当前的状态机处于什么状态。 然后将事件处理为一个个的方法每个方法中会操作状态机修改状态有需要的情况下在修改状态的同时还可以执行某些动作。
把通用部分提取出来后可以得到这样一个通用类图
可以看到上面的StateMachine和State关系是双向的这是因为状态机需要持有状态对象来表示当前状态以及通过当前的状态对象中的方法进行状态的流转而流转的结果需要重新set到状态机中又要求State必须持有状态机对象。 当然这里State对StateMachine的关系也可以通过依赖来表示。
2.1.订单状态流转案例
假设现在有一个商品订单的状态流转需求状态图如下 这里没有加退款的状态后续的拓展例子上会加上用这种方式来体验状态模式的拓展性。
我们拿着这个图的时候可以简单的在脑海里面过一遍如果通过if/else或者switch来做应该要怎么写后续如果想把退款的状态加入进去又该怎么拓展这种方式应该大家都会就不在这里赘述了。
接下来就一步步的通过状态模式来实现这么一个状态机。
2.1.1.状态枚举定义
定义状态枚举主要是为了统一状态常量因为订单是需要落库的我们在持久化到数据库时不能把状态对象保存进去所以会涉及到状态常量与状态对象的互相转换。定义的枚举如下
import lombok.Getter;Getter
public enum OrderStateEnum {WAIT_PAYMENT(1, 待支付),WAIT_DELIVER(2, 待发货),WAIT_RECEIVE(3, 待收货),RECEIVED(4, 已收货),CANCEL(5, 已取消);private final int state;private final String desc;OrderStateEnum(int state, String desc) {this.state state;this.desc desc;}public int getState() {return state;}public String getDesc() {return desc;}
}2.1.2.状态接口与实现
先上代码
public interface OrderState {OrderStateEnum orderStateType();default void pay(OrderStateMachine stateMachine) {System.out.println(|–当前订单状态不支持支付已忽略);}default void cancel(OrderStateMachine stateMachine) {System.out.println(|–当前订单状态不支持取消已忽略);}default void deliver(OrderStateMachine stateMachine) {System.out.println(|–当前订单状态不支持发货已忽略);}default void receive(OrderStateMachine stateMachine) {System.out.println(|–当前订单状态不支持收货已忽略);}
}接口中定义的pay,cancel等方法就是事件供子类进行实现相信大家也发现了这些事件没有定义成抽象方法而是通过default定义成了一个实例方法。不太清楚为什么的同学可以先思考一下为什么要这么定义。
其实这么定义的好处是各个状态子类只需要实现自己需要的方法而不用把所有的方法都实现一遍这种做法在Spring中也比较常见在JDK8之前通常是用xxxWrapper来实现的JDK8之后就重构为直接使用default方法来实现了。
举个例子后续如果需要加入退款状态接口中也会新增一个提交退款的事件在各个子类中选择需要实现提交退款事件的状态子类进行重写即可而不需要所有的子类都重写。 有多少个状态就有多少个实现类并按照上面的状态图在对应的状态中实现自己需要的事件。
待支付状态有支付和取消两种事件public class WaitPaymentState implements OrderState {Overridepublic OrderStateEnum orderStateType() {return OrderStateEnum.WAIT_PAYMENT;}Overridepublic void pay(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new WaitDeliverState());}Overridepublic void cancel(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new CancelState());}
}待发货状态有发货事件public class WaitDeliverState implements OrderState {Overridepublic OrderStateEnum orderStateType() {return OrderStateEnum.WAIT_DELIVER;}Overridepublic void deliver(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new WaitReceiveState());}
}待收货状态有收货事件public class WaitReceiveState implements OrderState {Overridepublic OrderStateEnum orderStateType() {return OrderStateEnum.WAIT_RECEIVE;}Overridepublic void receive(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new ReceivedState());}
}已收货状态状态结束点没有其他事件public class ReceivedState implements OrderState {Overridepublic OrderStateEnum orderStateType() {return OrderStateEnum.RECEIVED;}}取消状态状态结束点没有其他事件public class CancelState implements OrderState {Overridepublic OrderStateEnum orderStateType() {return OrderStateEnum.CANCEL;}
}2.1.3.状态机
状态机中需要持有当前状态对象同时需要把状态接口中的事件同步定义到状态机中以便外部业务对象调用。 除此之外状态枚举常量与状态对象之间的映射关系也可以直接配置在当前状态机中功能更加内聚。
public class OrderStateMachine {public static final MapOrderStateEnum, OrderState ORDER_STATE_MAP new HashMap();static {ORDER_STATE_MAP.put(OrderStateEnum.WAIT_PAYMENT, new WaitPaymentState());ORDER_STATE_MAP.put(OrderStateEnum.WAIT_DELIVER, new WaitDeliverState());ORDER_STATE_MAP.put(OrderStateEnum.WAIT_RECEIVE, new WaitReceiveState());ORDER_STATE_MAP.put(OrderStateEnum.RECEIVED, new ReceivedState());ORDER_STATE_MAP.put(OrderStateEnum.CANCEL, new CancelState());}private OrderState currentState;public OrderStateMachine(OrderStateEnum orderStateEnum) {this.currentState ORDER_STATE_MAP.get(orderStateEnum);}public OrderState getCurrentState() {return currentState;}public void setCurrentState(OrderState currentState) {this.currentState currentState;}void pay() {currentState.pay(this);}void deliver() {currentState.deliver(this);}void receive() {currentState.receive(this);}void cancel() {currentState.cancel(this);}}2.1.4.测试
做一下状态机的测试由于打印的日志重复度很高这里取了个巧将函数作为参数封装了一下
public class OrderService {public static void main(String[] args) {OrderStateMachine stateMachine new OrderStateMachine(OrderStateEnum.WAIT_DELIVER);invoke(stateMachine::pay, 用户支付, stateMachine);invoke(stateMachine::deliver, 商家发货, stateMachine);invoke(stateMachine::receive, 用户收货, stateMachine);invoke(stateMachine::cancel, 取消支付, stateMachine);}public static void invoke(Runnable runnable, String desc, OrderStateMachine stateMachine) {System.out.println(desc 前订单状态: stateMachine.getCurrentState().orderStateType().getDesc());runnable.run();System.out.println(desc 后订单状态: stateMachine.getCurrentState().orderStateType().getDesc());System.out.println(——————);}
}以待发货作为状态常量创建了一个状态机状态机当前的状态就是待发货下面的四个调用中第1,4个是不会改变状态的第2,3个会改变状态下面以执行结果来验证猜测
用户支付前订单状态: 待发货
|–当前订单状态不支持支付已忽略
用户支付后订单状态: 待发货
商家发货前订单状态: 待发货
商家发货后订单状态: 待收货
用户收货前订单状态: 待收货
用户收货后订单状态: 已收货
取消支付前订单状态: 已收货 |–当前订单状态不支持取消已忽略 取消支付后订单状态: 已收货 ——————2.2.退款状态的拓展 通过状态模式来实现状态机看重的就是它带来的拓展性和易维护性所以在原有的基础上加上退款的事件和状态一起看看需要做些什么事。 2.2.1.代码拓展 下面是加入了退款的状态图 通过状态图可以看到需要加入 两个状态退款中和已退款两个事件申请退款和确认退款原有状态拓展待发货、待收货、已收货 3个状态中都需要引入申请退款事件 综上一步一步的拓展代码 第一步拓展枚举常量public enum OrderStateEnum {WAIT_PAYMENT(1, 待支付),WAIT_DELIVER(2, 待发货),WAIT_RECEIVE(3, 待收货),RECEIVED(4, 已收货),CANCEL(5, 已取消),REFUNDING(6, 退款中),REFUNDED(7, 已退款),;// 省略后续代码…… }第二步拓展状态接口public interface OrderState {// 省略已有代码……default void refund(OrderStateMachine stateMachine) {System.out.println(|–当前订单状态不支持退款已忽略);}default void confirmRefund(OrderStateMachine stateMachine) {System.out.println(当前订单状态不支持确认退款已忽略);} }第三步新增两个状态退款中与已退款 public class RefundingState implements OrderState {Overridepublic OrderStateEnum name() {return OrderStateEnum.REFUNDING;}Overridepublic void confirmRefund(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new RefundedState());} }public class RefundedState implements OrderState {Overridepublic OrderStateEnum name() {return OrderStateEnum.REFUNDED;} }第四步拓展原有状态待发货待收货已收货 public class WaitDeliverState implements OrderState {// 省略已有代码……Overridepublic void refund(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new RefundingState());} }public class WaitReceiveState implements OrderState {// 省略已有代码……Overridepublic void refund(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new RefundingState());}}public class ReceivedState implements OrderState {// 省略已有代码……Overridepublic void refund(OrderStateMachine stateMachine) {stateMachine.setCurrentState(new RefundingState());}}第五步拓展状态机 public class OrderStateMachine {public static final MapOrderStateEnum, OrderState ORDER_STATE_MAP new HashMap();static {// 省略已有状态……ORDER_STATE_MAP.put(OrderStateEnum.REFUNDING, new RefundingState());ORDER_STATE_MAP.put(OrderStateEnum.REFUNDED, new RefundedState());}// 省略已有方法……void refund() {currentState.refund(this);}void confirmRefund() {currentState.confirmRefund(this);} }2.2.2.测试 在上面的代码中可以看到都是在对配置进行追加而没有对原有的逻辑做任何的修改然后写一个测试 public class OrderService {public static void main(String[] args) {OrderStateMachine stateMachine new OrderStateMachine(OrderStateEnum.WAIT_DELIVER);invoke(stateMachine::pay, 用户支付, stateMachine);invoke(stateMachine::deliver, 商家发货, stateMachine);invoke(stateMachine::receive, 用户收货, stateMachine);invoke(stateMachine::cancel, 取消支付, stateMachine);invoke(stateMachine::refund, 申请退款, stateMachine);invoke(stateMachine::confirmRefund, 确认退款, stateMachine);}public static void invoke(Runnable runnable, String desc, OrderStateMachine stateMachine) {System.out.println(desc 前订单状态: stateMachine.getCurrentState().orderStateType().getDesc());runnable.run();System.out.println(desc 后订单状态: stateMachine.getCurrentState().orderStateType().getDesc());System.out.println(——————);}}查看日志是否触发退款 用户支付前订单状态: 待发货 |–当前订单状态不支持支付已忽略
用户支付后订单状态: 待发货
商家发货前订单状态: 待发货
商家发货后订单状态: 待收货
用户收货前订单状态: 待收货
用户收货后订单状态: 已收货
取消支付前订单状态: 已收货 |–当前订单状态不支持取消已忽略
取消支付后订单状态: 已收货
申请退款前订单状态: 已收货
申请退款后订单状态: 退款中
确认退款前订单状态: 退款中 确认退款后订单状态: 已退款 ——————2.3.小结 从上面的代码可以看到通过状态模式可以很轻松的对状态进行拓展。 不过上面的例子中没有对状态机中的动作进行实现其实动作和状态转换的逻辑放在一起就可以了即通过事件方法调用 可以变更状态同时也能够触发对应的动作。 此外代码中只是状态机的流程实际的开发中应该将状态机关联到对应的业务实体中通过业务实体的实时状态来创建状态机在完成状态流转之后再将状态更新到业务实体中。 3.总结 本篇主要讲述了如何通过状态模式来实现一个状态机。状态模式的实现代码结构清晰相对于if/else,switch拓展性强同时也起到了良好的封装效果状态在状态机内部流转业务流程不需要关心状态到底是怎么流转的。 当然缺点就是类膨胀问题类会比较多如果状态非常复杂的情况下也可以采取其他办法来实现状态机例如查表法。 总之要分析并实现一个业务流程中的状态流转的时候先画出状态图以状态图为指导来选择状态机的实现方式即可在状态相对不那么复杂的情况下可以优先考虑使用状态模式。 附:《【UML建模】状态图State Machine Diagram》
- 上一篇: 唐山免费网站制作全球速卖通
- 下一篇: 唐山乾正建设工程材料检测公司网站网站开发实战教程
相关文章
-
唐山免费网站制作全球速卖通
唐山免费网站制作全球速卖通
- 技术栈
- 2026年03月21日
-
唐山论坛建站模板合肥做网站首选 晨飞网络
唐山论坛建站模板合肥做网站首选 晨飞网络
- 技术栈
- 2026年03月21日
-
唐山滦县网站建设天津做手机网站建设
唐山滦县网站建设天津做手机网站建设
- 技术栈
- 2026年03月21日
-
唐山乾正建设工程材料检测公司网站网站开发实战教程
唐山乾正建设工程材料检测公司网站网站开发实战教程
- 技术栈
- 2026年03月21日
-
唐山市网站建设昆明做网站要多少钱
唐山市网站建设昆明做网站要多少钱
- 技术栈
- 2026年03月21日
-
唐山市网站建设如何做网站推广及优化
唐山市网站建设如何做网站推广及优化
- 技术栈
- 2026年03月21日
