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代码
|
*/
|
}
|