设计模式(实战项目)-状态模式

需求背景:存在状态流转的预约单

一.数据库设计

CREATE TABLE `appointment` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `appoint_type` int(11) NOT NULL COMMENT '预约类型(0:线下查房...)',
  `appoint_user_id` bigint(20) NOT NULL COMMENT '预约人userId',
  `appoint_store_id` bigint(20) NOT NULL COMMENT '预约门店',
  `appoint_service_type` int(11) DEFAULT NULL COMMENT '预约服务类型(9:儿科查房 7:产科查房 8:中医查房)',
  `appoint_doctor_id` bigint(11) DEFAULT NULL COMMENT '预约医生id',
  `appoint_date` date DEFAULT NULL COMMENT '预约日期(精确到日)',
  `appoint_time_start` time NOT NULL COMMENT '预约开始时间',
  `appoint_time_end` time NOT NULL COMMENT '预约结束时间',
  `status` int(11) NOT NULL COMMENT '状态(-1:已取消 0:待接单 1:待分配(已拒绝) 2:待查房 3:待小结 4:待签名 100:已完成 )',
  `drive_appointment_id` bigint(20) DEFAULT NULL COMMENT '驱动预约单id(null:代表驱动预约单)',
  `appointment_setting_id` bigint(20) DEFAULT NULL COMMENT '预约单-配置id',
  `create_id` bigint(20) DEFAULT NULL COMMENT '创建人id',
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `modify_id` bigint(20) DEFAULT NULL COMMENT '修改人',
  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  `deleted` tinyint(1) DEFAULT '0' COMMENT '删除标记;0-正常 ;1-删除',
  PRIMARY KEY (`id`),
  KEY `idx_drive_appointment_id` (`drive_appointment_id`) USING BTREE,
  KEY `idx_appointment_setting_id` (`appointment_setting_id`) USING BTREE,
  KEY `idx_appoint_user_id` (`appoint_user_id`) USING BTREE
)  AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4  COMMENT='预约单';




-- 预约单-状态流转表
 CREATE TABLE `stbella-his`.appointment_status_log
( 
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
	appointment_id    bigint(20)						not null COMMENT '预约单id',
	before_status 	  int(11)							  NOT null COMMENT '前状态',
  after_status 	    int(11)							  NOT null COMMENT '后状态',
	handle_type       int(11)								not null COMMENT '操作类型',
	handle_user_type    int(11)					    not null COMMENT '操作人类型',
  create_id bigint(20) DEFAULT NULL COMMENT '创建人id',
	gmt_create datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
	modify_id bigint(20) DEFAULT NULL COMMENT '修改人',
	gmt_modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
	deleted tinyint(1) DEFAULT '0' COMMENT '删除标记;0-正常 ;1-删除',
	 PRIMARY KEY (`id`),
	 KEY `idx_appointment_id` (`appointment_id`) USING BTREE
)  
   comment '预约单-状态流转表'; 

二.状态枚举类

@Getter
@AllArgsConstructor
public enum AppointStatusEnum {

	

	INIT(-100, "初始化"),
	CANCEL(-1, "已取消"),
	WAIT_RECEIVE(0, "待接单"),
	WAIT_DISTRIBUTE(1, "待分配"),
	WAIT_CHECK_ROOM(2, "待查房"),
	WAIT_SUMMARY(3, "待小结"),
	WAIT_SIGN(4, "待签名"),
	COMPLETE(100, "已完成");


	private final int code;

	private final String name;

	public static AppointStatusEnum getEnum(int code) {
		for (AppointStatusEnum statusEnum : AppointStatusEnum.values()) {
			if (statusEnum.getCode() == code) {
				return statusEnum;
			}
		}
		return null;
	}

}

三. 上下文参数类:参数传递

@Builder
@Data
public class AppointContext implements Serializable {

	private static final long serialVersionUID = 3542771730176821092L;

	private UserTokenInfoDTO userTokenInfoDTO;

	private ClientEnum clientEnum;

	private AppointPO appointPO;

}

四.状态机流转上下文类:所有要执行的动作都在这里记录

@Data
public class AppointHandleContext implements Serializable {
	private static final long serialVersionUID = 1658366511210864400L;

	private IAppointStatusHandler statusHandler = AppointStatusHandlerFactory.getStatusHandler(AppointStatusEnum.INIT);

	public AppointDetailVO detail(AppointHandleContext handleContext, 
	public Boolean cancel(AppointHandleContext handleContext, AppointContext context) {
		return statusHandler.cancel(handleContext, context);
	}

	public String add(AppointHandleContext handleContext, AppointContext context) {
		return statusHandler.add(handleContext, context);
	}

	public Boolean update(AppointHandleContext handleContext, AppointContext context) {
		return statusHandler.update(handleContext, context);
	}

	

}

五.状态处理器工厂类

@Component
public class AppointStatusHandlerFactory implements ApplicationContextAware {

	private static final Map<AppointStatusEnum, IAppointStatusHandler> MAP = Maps.newHashMapWithExpectedSize(AppointStatusEnum.values().length);

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		Map<String, IAppointStatusHandler> beansOfType = applicationContext.getBeansOfType(IAppointStatusHandler.class);
		if (CollectionUtil.isEmpty(beansOfType)) {
			return;
		}
		beansOfType.forEach((key, statusHandler) -> MAP.put(statusHandler.getStatus(), statusHandler));
	}


	public static IAppointStatusHandler getStatusHandler(AppointStatusEnum appointStatusEnum) {
		return Optional.ofNullable(MAP.get(appointStatusEnum))
				.orElseThrow(() -> new BusinessException(ResultEnum.PARAM_ERROR, "预约单状态异常"));
	}

}

六.状态接口类

public interface IAppointStatusHandler {

	AppointStatusEnum getStatus();

	AppointDetailVO detail(AppointHandleContext handleContext, AppointContext context);

	Boolean cancel(AppointHandleContext handleContext, AppointContext context);

	String add(AppointHandleContext handleContext, AppointContext context);

	Boolean update(AppointHandleContext handleContext, AppointContext context);

」

七.状态抽象实现类

@Slf4j
@Component
public abstract class AbstractAppointStatusHandler implements IAppointStatusHandler {

	private static final String LOG_PRE = "预约单状态流转异常,method:{},handleContext:{},context:{}";


	@Override
	public AppointDetailVO detail(AppointHandleContext handleContext, AppointContext context) {
		log.error(LOG_PRE, "detail", JSONUtil.toJsonStr(handleContext), JSONUtil.toJsonStr(context));
		throw new BusinessException(ResultEnum.PARAM_ERROR, "当前状态不允许查询");
	}

	@Override
	public Boolean cancel(AppointHandleContext handleContext, AppointContext context) {
		log.error(LOG_PRE, "cancel", JSONUtil.toJsonStr(handleContext), JSONUtil.toJsonStr(context));
		throw new BusinessException(ResultEnum.PARAM_ERROR, "当前状态不允许取消");
	}

	@Override
	public String add(AppointHandleContext handleContext, AppointContext context) {
		log.error(LOG_PRE, "add", JSONUtil.toJsonStr(handleContext), JSONUtil.toJsonStr(context));
		throw new BusinessException(ResultEnum.PARAM_ERROR, "当前状态不允许新增");
	}

	@Override
	public Boolean update(AppointHandleContext handleContext, AppointContext context) {
		log.error(LOG_PRE, "update", JSONUtil.toJsonStr(handleContext), JSONUtil.toJsonStr(context));
		throw new BusinessException(ResultEnum.PARAM_ERROR, "当前状态不允许修改");
	}
}

八.每个状态节点实现类

@Slf4j
@Component
public class AppointInitHandler extends AbstractAppointStatusHandler {

	

	@Override
	public AppointStatusEnum getStatus() {
		return AppointStatusEnum.INIT;
	}

	@Override
	public AppointDetailVO detail(AppointHandleContext handleContext, AppointContext context) {
		return appointSupport.detail(context);
	}

	@Override
	public String add(AppointHandleContext handleContext, AppointContext context) 
    {
		
	}

}
@Slf4j
@Component
public class AppointWaitCheckRoomHandler extends AbstractAppointStatusHandler {
	@Override
	public AppointStatusEnum getStatus() {
		return AppointStatusEnum.WAIT_CHECK_ROOM;
	}

	@Resource
	private AppointSupport appointSupport;

	@Override
	public AppointDetailVO detail(AppointHandleContext handleContext, AppointContext context) {
		AppointDetailVO detail = appointSupport.detail(context);
		ClientEnum clientEnum = context.getClientEnum();
		AppointPO appointPO = context.getAppointPO();

		switch (clientEnum) {
			case HIS_NURSE:
				this.nurseDetail(detail, appointPO);
				break;
			case HIS_DOCTOR:
				this.doctorDetail(detail, appointPO);
				break;
			default:
				break;
		}
		return detail;
	}

	@Override
	public Boolean cancel(AppointHandleContext handleContext, AppointContext context) {
		return appointSupport.handleOnlyStatus(context, AppointStatusEnum.CANCEL, AppointHandleTypeEnum.CANCEL);
	}


	@Override
	public Boolean startCheckRoom(AppointHandleContext handleContext, AppointContext context) {
		return appointSupport.handleOnlyStatus(context, AppointStatusEnum.WAIT_SUMMARY, AppointHandleTypeEnum.START_CHECK_ROOM);
	}
@Slf4j
@Component
public class AppointCompleteHandler extends AbstractAppointStatusHandler {

	@Override
	public AppointStatusEnum getStatus() {
		return AppointStatusEnum.COMPLETE;
	}


	@Override
	public AppointDetailVO detail(AppointHandleContext handleContext, AppointContext context) {
		AppointDetailVO detail = appointSupport.detail(context);
		ClientEnum clientEnum = context.getClientEnum();
		AppointPO appointPO = context.getAppointPO();

		switch (clientEnum) {
			case HIS_NURSE:
				this.nurseDetail(detail, appointPO);
				break;
			case HIS_DOCTOR:
				this.doctorDetail(detail, appointPO);
				break;
			default:
				break;
		}
		return detail;
	}



	@Override
	public AppointCheckRoomSignNotifyVO getAppointCheckRoomSignNotifyVO(AppointHandleContext handleContext, AppointContext context) {
		
	}
}

九.具体行为调用代码类

@Override
	public void bindPicpCustomer(AppointClinicBindReq req, UserTokenInfoDTO userTokenInfoDTO) {
		AppointPO appointPO = Optional.ofNullable(appointRepository.getOnePOById(req.getAppointmentId())).orElseThrow(() ->
				new BusinessException(ResultEnum.PARAM_ERROR, "预约单数据不存在或已被删除"));

		AppointHandleContext handleContext = new AppointHandleContext();
		handleContext.setStatusHandler(AppointStatusHandlerFactory.getStatusHandler(AppointStatusEnum.getEnum(appointPO.getStatus())));
		handleContext.bindPicpCustomer(handleContext, AppointContext.builder()
				.appointPO(appointPO)
				.clientEnum(appointSupport.getLoginClientEnum(userTokenInfoDTO))
				.userTokenInfoDTO(userTokenInfoDTO)
				.picpUsers(req.getPicpUsers())
				.build());
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/761529.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue项目创建+eslint+Prettier+git提交规范(commitizen+hooks+husk)

# 步骤 1、使用 vue-cli 创建项目 这一小节我们需要创建一个 vue3 的项目&#xff0c;而创建项目的方式依然是通过 vue-cli 进行创建。 不过这里有一点大家需要注意&#xff0c;因为我们需要使用最新的模板&#xff0c;所以请保证你的 vue-cli 的版本在 4.5.13 以上&#xff…

基于X86+FPGA+AI的芯片缺陷检测方案

应用场景 随着半导体技术的发展&#xff0c;对芯片的良率要求越来越高。然而集成电路芯片制造工艺复杂&#xff0c;其制造过程中往往产生很多缺陷&#xff0c;因此缺陷检测是集成电路制造过程中的必备工艺。 客户需求 小体积&#xff0c;低功耗 2 x USB,1 x LAN Core-i平台无…

YOLOv8 目标检测程序,依赖的库最少,使用onnxruntime推理

YOLOv8 目标检测程序&#xff0c;依赖的库最少&#xff0c;使用onnxruntime推理 flyfish 为了方便理解&#xff0c;加入了注释 """ YOLOv8 目标检测程序 Author: flyfish Date: Description: 该程序使用ONNX运行时进行YOLOv8模型的目标检测。它对输入图像进行…

AQS同步队列、条件队列源码解析

AQS详解 前言AQS几个重要的内部属性字段内部类 Node同步队列 | 阻塞队列等待队列 | 条件队列 重要方法执行链同步队列的获取、阻塞、唤醒加锁代码流程解锁 条件队列的获取、阻塞、唤醒大体流程 调用await()方法1. 将节点加入到条件队列2. 完全释放独占锁3. 等待进入阻塞队列4. …

【刷题汇总--数字统计、两个数组的交集、点击消除(栈)】

C日常刷题积累 今日刷题汇总 - day0011、数字统计1.1、题目1.2、思路1.3、程序实现 2、两个数组的交集2.1、题目2.2、思路2.3、程序实现 3、点击消除(栈)3.1、题目3.2、思路3.3、程序实现 今日刷题汇总 - day001 1、数字统计 1.1、题目 请统计某个给定范围[L, R]的所有整数中…

reactjs18 中使用@reduxjs/toolkit同步异步数据的使用

react18 中使用reduxjs/toolkit 1.安装依赖包 yarn add reduxjs/toolkit react-redux2.创建 store 根目录下面创建 store 文件夹&#xff0c;然后创建 index.js 文件。 import { configureStore } from "reduxjs/toolkit"; import { counterReducer } from "…

【机器学习】语音转文字 - FunASR 的应用与实践(speech to text)

本文将介绍 FunASR&#xff0c;一个多功能语音识别模型&#xff0c;包括其特点、使用方法以及在实际应用中的表现。我们将通过一个简单的示例来展示如何使用 FunASR 将语音转换为文字&#xff0c;并探讨其在语音识别领域的应用前景。 一、引言 随着人工智能技术的不断发展&am…

达梦数据库系列—19. 动态增加实时备库

目录 动态增加实时备库 1、数据准备 2 、配置新备库 2.1配置 dm.ini 2.2配置 dmmal.ini 2.3 配置 dmarch.ini 2.4 配置 dmwatcher.ini 2.5 启动备库 2.6 设置 OGUID 2.7 修改数据库模式 3、 动态添加 MAL 配置 4、 动态添加归档配置 5、 修改监视器 dmmonitor.ini…

软考初级网络管理员__网站单选题

1.以下关于服务器端脚本的说法中&#xff0c;正确的是()。 Script 编写 只能采用VBScript 编写 浏览器不能解释执行 由服务器发送到客户端&#xff0c;客户端负责运行 2.站点首页最常用的文件名是()。 index.html homepage.html resource.html mainfrm.html 3.在HTML…

Vatee万腾平台:引领行业变革,创新未来

在当今这个快速变化的时代&#xff0c;科技的力量正在以前所未有的速度推动着行业的变革。Vatee万腾平台&#xff0c;以其独特的视角和前瞻性的布局&#xff0c;正引领着行业变革的浪潮&#xff0c;创新着未来的发展方向。 Vatee万腾平台是一家专注于科技研发和创新应用的领军企…

面试突击:ConcurrentHashMap 源码详解

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。这篇文章想和大家聊聊 ConcurrentHashMap 相关的知识点。严格来说&#xff0c;ConcurrentHashMap 属于java.lang.cur…

【电源拓扑】PFC

为什么开关电源中都有PFC电路 PFC电路就是功率矫正电路&#xff0c;目的是为了防止杂波对电网产生冲击 AC220V通过整流桥之后电压和电流的波形分析 PFC电路为什么选择是Boost升压电路 PFC电路为什么要把电压升高到400V 为了解决输入电压低于滤波电容电压这个矛盾&#xff0…

LDM-XRNY-102溜槽堵塞开关 JOSEF约瑟 接点容量:5A/380V

工作原理 当物料在溜槽中造成堵塞时&#xff0c;堆积的物料会给溜槽侧壁一个压力&#xff0c;从而推动LDM-XRNY-102溜槽堵塞开关的活动门向外或向内推移&#xff08;根据具体设计而定&#xff09;。 当活动门偏转一个设定的角度时&#xff0c;其控制开关会动作&#xff0c;发出…

基于Python的自动化测试框架-Pytest总结-第一弹基础

Pytest总结第一弹基础 入门知识点安装pytest运行pytest测试用例发现规则执行方式命令行执行参数 配置发现规则 如何编写测试Case基础案例断言语句的使用pytest.fail() 和 Exceptions自定义断言函数异常测试测试类形式 pytest的Fixture使用Fixture入门案例使用fixture的Setup、T…

[A133]全志u-boot中的I2C驱动分析

[A133]全志u-boot中的I2C驱动分析 hongxi.zhu 2024-6-27 一、IIC标准读写时序 IIC是高位(MSB)先传输 二、代码流程 2.1主机写数据 brandy/brandy-2.0/u-boot-2018/drivers/i2c/sunxi_i2c.c static int sunxi_i2c_write(struct i2c_adapter *adap, uint8_t chip,uint32_t addr…

深入解析 androidx.databinding.BaseObservable

在现代 Android 开发中&#xff0c;数据绑定 (Data Binding) 是一个重要的技术&#xff0c;它简化了 UI 和数据之间的交互。在数据绑定框架中&#xff0c;androidx.databinding.BaseObservable 是一个关键类&#xff0c;用于实现可观察的数据模型。本文将详细介绍 BaseObservab…

Centos7安装Minio笔记

一、Minio概述 Minio是一款开源的对象存储服务器&#xff0c;可以运行在多种操作系统上&#xff0c;包括Linux、Windows和MacOS等。提供一种简单、可扩展、高可用的对象存储解决方案&#xff0c;支持多种数据格式&#xff0c;包括对象、块和文件等。Minio是一款强大、灵活、可…

基于若依(ruoyi-vue)的周报管理系统

喂wangyinlon 填报人页面 审批人 审批不通过,填报人需要重新填写.

智慧校园新气象:校园气象站

在数字化、智能化的浪潮下&#xff0c;传统校园正在迎来一场革命性的变革。在这场变革中&#xff0c;校园气象站以其独特的功能和魅力&#xff0c;成为推动校园气象科普教育、提升校园品质的重要力量。 一、校园气象站&#xff1a;智慧校园的“气象眼” 校园气象站&#xff0c…

宠物医院管理系统-计算机毕业设计源码07221

目 录 1 绪论 1.1 选题背景和意义 1.2国内外研究现状 1.3论文结构与章节安排 2 宠物医院管理系统系统分析 2.1 可行性分析 2.1.1技术可行性分析 2.1.2 操作可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分…
最新文章