package com.smartor.statemachine; /** * 住院状态机使用示例 * * 本类展示如何在现有代码中集成状态机,仅供参考,不需要运行 * * @author smartor */ public class InhospStateMachineExample { /** * 示例1: 在ServiceSLTDHealthcareRecordServiceImpl中使用状态机 * * 原方法签名: * private void processPatientInhospInfo(ServiceSLTDInhospResDTO dto, PatArchive patArchive, String cry) * * 改造方案:用状态机替换原有的if-else逻辑 */ public void exampleUsageInService() { /* // 原代码(561-677行)改造为: @Autowired private InhospStateMachineService stateMachineService; private void processPatientInhospInfo(ServiceSLTDInhospResDTO dto, PatArchive patArchive, String cry) { // 构建住院记录对象(保持原有逻辑) PatMedInhosp patMedInhosp = buildPatientInhospInfo(dto, patArchive, cry); // 使用状态机处理状态转换(替换原有的大段if-else) boolean success = stateMachineService.processStateChange(patMedInhosp, cry); if (success) { log.info("【processPatientInhospInfo】状态转换成功:serialnum={}, cry={}", patMedInhosp.getSerialnum(), cry); } else { log.warn("【processPatientInhospInfo】状态转换失败或跳过:serialnum={}, cry={}", patMedInhosp.getSerialnum(), cry); } } // 优点: // 1. 代码从100+行减少到10行 // 2. 状态转换逻辑清晰,易于维护 // 3. 自动加分布式锁,解决并发问题 // 4. 状态校验规则集中管理 */ } /** * 示例2: 直接使用状态机服务API */ public void exampleDirectUsage() { /* @Autowired private InhospStateMachineService stateMachineService; // 处理预入院 PatMedInhosp preAdmission = new PatMedInhosp(); preAdmission.setSerialnum("202601290001"); preAdmission.setOrgid("HOS001"); preAdmission.setPatno("P001"); // ... 设置其他字段 boolean result1 = stateMachineService.processPreAdmission(preAdmission); // 处理入院(会自动从预入院状态转换) PatMedInhosp inHospital = new PatMedInhosp(); inHospital.setSerialnum("202601290001"); inHospital.setOrgid("HOS001"); inHospital.setPatno("P001"); // ... 设置其他字段 boolean result2 = stateMachineService.processInHospital(inHospital); // 处理出院(会自动从入院状态转换) PatMedInhosp discharge = new PatMedInhosp(); discharge.setSerialnum("202601290001"); discharge.setOrgid("HOS001"); discharge.setPatno("P001"); // ... 设置其他字段 boolean result3 = stateMachineService.processDischarge(discharge); // 查询当前状态 String currentState = stateMachineService.getCurrentState("202601290001", "HOS001", "P001"); // currentState = "1" (出院状态) */ } /** * 示例3: 状态转换校验 */ public void exampleStateValidation() { /* // 非法转换示例1:预入院直接到出院(会抛出异常) try { PatMedInhosp discharge = new PatMedInhosp(); discharge.setSerialnum("202601290002"); discharge.setOrgid("HOS001"); discharge.setPatno("P002"); discharge.setInhospstate("3"); // 当前是预入院 stateMachineService.processDischarge(discharge); // 尝试直接出院 } catch (StateTransitionException e) { log.error("状态转换失败:{}", e.getMessage()); // 输出: 非法的状态转换: 从 [3] 到 [1] } // 非法转换示例2:重复入院(会被handler拒绝) PatMedInhosp inHospital1 = new PatMedInhosp(); inHospital1.setSerialnum("202601290003"); inHospital1.setOrgid("HOS001"); inHospital1.setPatno("P003"); stateMachineService.processInHospital(inHospital1); // 第一次入院:成功 boolean result = stateMachineService.processInHospital(inHospital1); // 第二次入院:失败 // result = false,日志输出警告 */ } /** * 状态机架构说明 * * 1. 状态枚举 (InhospStateEnum) * - 定义所有状态及允许的转换规则 * - PRE_ADMISSION(3) -> IN_HOSPITAL(0) -> DISCHARGED(1) * * 2. 状态处理器 (InhospStateHandler) * - PreAdmissionHandler: 处理预入院逻辑 * - InHospitalHandler: 处理入院逻辑 * - DischargeHandler: 处理出院逻辑 * * 3. 状态机管理器 (InhospStateMachine) * - 协调状态转换 * - 管理分布式锁 * - 验证状态合法性 * * 4. 门面服务 (InhospStateMachineService) * - 提供便捷API * - 封装复杂逻辑 * * 5. 异常处理 (StateTransitionException) * - 处理非法状态转换 */ /** * 数据库配合建议 * * 1. 添加唯一索引(建议) * CREATE UNIQUE INDEX uk_serialnum_orgid_state * ON pat_med_inhosp(serialnum, orgid, inhospstate); * * 2. 或者更严格的约束(确保一个患者只有一条记录) * CREATE UNIQUE INDEX uk_serialnum_orgid * ON pat_med_inhosp(serialnum, orgid); * * 注意:如果使用第2种索引,需要确保: * - 状态变更必须走更新(不能插入新记录) * - 需要清理历史多状态记录 */ /** * 渐进式集成方案 * * 阶段1:双写模式(推荐) * - 保留原有代码不变 * - 新增状态机调用,记录日志对比 * - 验证状态机逻辑正确性 * * 阶段2:灰度切换 * - 部分cry值走状态机 * - 观察生产环境表现 * * 阶段3:完全迁移 * - 全部逻辑切换到状态机 * - 移除原有if-else代码 */ }