目录
- 一、设计模式总体概述
- [1.1 定义](#1.1 定义)
- [1.2 为什么HIS/LIS系统需要设计模式](#1.2 为什么HIS/LIS系统需要设计模式)
- [1.3 三大分类总览](#1.3 三大分类总览)
- 二、创建型设计模式(全6种)
- [2.1 单例模式](#2.1 单例模式)
- [2.2 简单工厂模式](#2.2 简单工厂模式)
- [2.3 工厂方法模式](#2.3 工厂方法模式)
- [2.4 抽象工厂模式](#2.4 抽象工厂模式)
- [2.5 建造者模式](#2.5 建造者模式)
- [2.6 原型模式](#2.6 原型模式)
- 三、结构型设计模式(全7种)
- [3.1 适配器模式](#3.1 适配器模式)
- [3.2 装饰器模式](#3.2 装饰器模式)
- [3.3 代理模式](#3.3 代理模式)
- [3.4 外观模式](#3.4 外观模式)
- [3.5 组合模式](#3.5 组合模式)
- [3.6 桥接模式](#3.6 桥接模式)
- [3.7 享元模式](#3.7 享元模式)
- 四、行为型设计模式(全11种)
- [4.1 策略模式](#4.1 策略模式)
- [4.2 模板方法模式](#4.2 模板方法模式)
- [4.3 观察者模式](#4.3 观察者模式)
- [4.4 责任链模式](#4.4 责任链模式)
- [4.5 状态模式](#4.5 状态模式)
- [4.6 命令模式](#4.6 命令模式)
- [4.7 迭代器模式](#4.7 迭代器模式)
- [4.8 中介者模式](#4.8 中介者模式)
- [4.9 备忘录模式](#4.9 备忘录模式)
- [4.10 访问者模式](#4.10 访问者模式)
- [4.11 解释器模式](#4.11 解释器模式)
- 五、设计模式选型速查表
- 六、总结
一、设计模式总体概述
1.1 定义
设计模式是面向对象软件设计中,针对反复出现的设计问题总结出的可复用、经验证的解决方案模板。核心目标是解耦、复用、可扩展、易维护,而非语法层面的技巧。
1.2 为什么HIS/LIS系统需要设计模式
医疗信息系统(HIS医院信息系统、LIS检验信息系统)具备以下典型特征:
-
业务规则复杂:收费、医保、检验、审核、报告多链路嵌套
-
政策迭代频繁:医保政策、收费标准、检验规范持续更新
-
第三方对接多:检验设备、医保接口、支付渠道、外设终端
-
稳定性要求极高:核心业务不允许因修改引发连锁故障
-
生命周期长:系统需支撑5~10年以上的业务迭代
无设计模式的系统普遍存在:硬编码泛滥、if/else嵌套爆炸、模块耦合严重、修改风险高、单元测试困难等问题。设计模式是医疗系统长期可维护性的核心保障。
1.3 三大分类总览
| 分类 | 核心作用 | 包含模式 |
|---|---|---|
| 创建型 | 管控对象创建逻辑,隔离实例化与业务逻辑 | 单例、简单工厂、工厂方法、抽象工厂、建造者、原型 |
| 结构型 | 组合类与对象形成灵活结构,实现功能扩展与适配 | 适配器、装饰器、代理、外观、组合、桥接、享元 |
| 行为型 | 定义对象间的职责分配、通信方式与流程控制 | 策略、模板方法、观察者、责任链、状态、命令、迭代器、中介者、备忘录、访问者、解释器 |
二、创建型设计模式(全6种)
2.1 单例模式
业务场景
HIS全局配置管理器、LIS设备日志中心、医保参数缓存、系统全局唯一资源池。
使用原因
全局唯一实例,避免重复加载配置、资源重复占用、数据状态不一致。
优缺点
✅ 全局唯一、节省资源、访问便捷
❌ 不利于单元测试、需处理线程安全
C# 实现
C#
/// <summary>
/// HIS全局配置管理器【双重校验锁线程安全单例】
/// </summary>
public sealed class HisConfigManager
{
private static volatile HisConfigManager? _instance;
private static readonly object _lock = new();
private readonly Dictionary<string, string> _configs;
// 私有构造,禁止外部实例化
private HisConfigManager()
{
_configs = new Dictionary<string, string>
{
{ "HospitalCode", "HOSP_202609" },
{ "InsuranceVersion", "INSUR_V3.2" },
{ "ReportAutoPrint", "true" }
};
}
/// <summary>
/// 获取全局唯一实例
/// </summary>
public static HisConfigManager Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
_instance ??= new HisConfigManager();
}
}
return _instance;
}
}
/// <summary>
/// 获取配置项
/// </summary>
public string GetConfig(string key)
{
return _configs.TryGetValue(key, out var value) ? value : string.Empty;
}
}
2.2 简单工厂模式
业务场景
LIS检验项目创建:血常规、尿常规、生化、免疫等检验申请单对象生成。
使用原因
统一封装对象创建逻辑,业务层无需关心具体实现类,传入类型即可获取实例。
优缺点
✅ 创建逻辑集中、业务代码简洁、易于维护
❌ 新增类型需修改工厂类,违反开闭原则
C# 实现
C#
/// <summary>
/// 检验项目抽象接口
/// </summary>
public interface ILisCheckItem
{
/// <summary>
/// 生成检验申请单
/// </summary>
void GenerateOrder();
}
/// <summary>
/// 血常规检验项目
/// </summary>
public class BloodRoutineCheck : ILisCheckItem
{
public void GenerateOrder()
{
Console.WriteLine("生成【血常规】申请单,绑定采血条码");
}
}
/// <summary>
/// 尿常规检验项目
/// </summary>
public class UrineRoutineCheck : ILisCheckItem
{
public void GenerateOrder()
{
Console.WriteLine("生成【尿常规】申请单,绑定尿样条码");
}
}
/// <summary>
/// LIS检验项目简单工厂
/// </summary>
public static class LisCheckItemFactory
{
/// <summary>
/// 根据类型创建检验项目
/// </summary>
public static ILisCheckItem Create(string checkType)
{
return checkType switch
{
"BloodRoutine" => new BloodRoutineCheck(),
"UrineRoutine" => new UrineRoutineCheck(),
_ => throw new ArgumentException($"不支持的检验类型:{checkType}")
};
}
}
2.3 工厂方法模式
业务场景
HIS支付渠道:微信支付、支付宝、医保统筹、现金支付,各渠道独立扩展。
使用原因
每个产品对应独立工厂,新增渠道不修改原有代码,完全符合开闭原则。
优缺点
✅ 符合开闭原则、扩展灵活、单一职责清晰
❌ 类数量膨胀、结构复杂度提升
C# 实现
C#
/// <summary>
/// 支付产品抽象接口
/// </summary>
public interface IHisPayment
{
void Pay(decimal amount);
}
/// <summary>
/// 微信支付实现
/// </summary>
public class WechatPayment : IHisPayment
{
public void Pay(decimal amount)
{
Console.WriteLine($"微信支付成功:{amount:F2}元");
}
}
/// <summary>
/// 医保统筹支付实现
/// </summary>
public class InsurancePayment : IHisPayment
{
public void Pay(decimal amount)
{
Console.WriteLine($"医保统筹支付成功:{amount:F2}元");
}
}
/// <summary>
/// 支付工厂抽象基类
/// </summary>
public abstract class PaymentFactoryBase
{
public abstract IHisPayment CreatePayment();
}
/// <summary>
/// 微信支付工厂
/// </summary>
public class WechatPaymentFactory : PaymentFactoryBase
{
public override IHisPayment CreatePayment() => new WechatPayment();
}
/// <summary>
/// 医保支付工厂
/// </summary>
public class InsurancePaymentFactory : PaymentFactoryBase
{
public override IHisPayment CreatePayment() => new InsurancePayment();
}
2.4 抽象工厂模式
业务场景
LIS多厂商检验设备族:罗氏、西门子两大厂商,每家都包含生化仪、血球仪两类设备,按厂商批量创建设备实例。
使用原因
创建一系列相关/相互依赖的产品族,统一厂商下设备创建逻辑,避免跨厂商混用。
优缺点
✅ 产品族统一创建、约束产品间依赖关系
❌ 新增产品族困难,扩展维度复杂
C# 实现
C#
#region 设备产品接口
/// <summary>
/// 生化仪接口
/// </summary>
public interface IBiochemicalDevice
{
string GetResult();
}
/// <summary>
/// 血球仪接口
/// </summary>
public interface ICytometerDevice
{
string GetResult();
}
#endregion
#region 罗氏设备族
public class RocheBiochemical : IBiochemicalDevice
{
public string GetResult() => "罗氏生化仪:血糖5.6mmol/L";
}
public class RocheCytometer : ICytometerDevice
{
public string GetResult() => "罗氏血球仪:白细胞6.5×10^9/L";
}
#endregion
#region 西门子设备族
public class SiemensBiochemical : IBiochemicalDevice
{
public string GetResult() => "西门子生化仪:肌酐78μmol/L";
}
public class SiemensCytometer : ICytometerDevice
{
public string GetResult() => "西门子血球仪:血小板220×10^9/L";
}
#endregion
#region 抽象工厂
/// <summary>
/// 检验设备抽象工厂
/// </summary>
public interface IDeviceFactory
{
IBiochemicalDevice CreateBiochemical();
ICytometerDevice CreateCytometer();
}
/// <summary>
/// 罗氏设备工厂
/// </summary>
public class RocheDeviceFactory : IDeviceFactory
{
public IBiochemicalDevice CreateBiochemical() => new RocheBiochemical();
public ICytometerDevice CreateCytometer() => new RocheCytometer();
}
/// <summary>
/// 西门子设备工厂
/// </summary>
public class SiemensDeviceFactory : IDeviceFactory
{
public IBiochemicalDevice CreateBiochemical() => new SiemensBiochemical();
public ICytometerDevice CreateCytometer() => new SiemensCytometer();
}
#endregion
2.5 建造者模式
业务场景
LIS检验报告、HIS住院病历、出院小结等复杂多字段对象构建,包含必填字段与大量可选字段。
使用原因
分步构建复杂对象,灵活选配字段,避免构造函数参数爆炸,提升代码可读性。
优缺点
✅ 构建逻辑清晰、参数灵活组合、必填可选分离
❌ 需额外编写Builder类,代码量略有增加
C# 实现
C#
/// <summary>
/// LIS检验报告实体(复杂对象)
/// </summary>
public class LisReport
{
// 必填字段
public string PatientId { get; }
public string CheckCode { get; }
public string DoctorName { get; }
// 可选字段
public string? Result { get; }
public string? ReferenceRange { get; }
public string? Remark { get; }
public DateTime? AuditTime { get; }
private LisReport(Builder builder)
{
PatientId = builder.PatientId;
CheckCode = builder.CheckCode;
DoctorName = builder.DoctorName;
Result = builder.Result;
ReferenceRange = builder.ReferenceRange;
Remark = builder.Remark;
AuditTime = builder.AuditTime;
}
/// <summary>
/// 检验报告建造者
/// </summary>
public class Builder
{
// 必填
public string PatientId { get; }
public string CheckCode { get; }
public string DoctorName { get; }
// 可选
public string? Result { get; set; }
public string? ReferenceRange { get; set; }
public string? Remark { get; set; }
public DateTime? AuditTime { get; set; }
public Builder(string patientId, string checkCode, string doctorName)
{
PatientId = patientId;
CheckCode = checkCode;
DoctorName = doctorName;
}
public Builder WithResult(string result)
{
Result = result;
return this;
}
public Builder WithReference(string range)
{
ReferenceRange = range;
return this;
}
public Builder WithRemark(string remark)
{
Remark = remark;
return this;
}
public Builder WithAuditTime(DateTime time)
{
AuditTime = time;
return this;
}
/// <summary>
/// 构建最终报告对象
/// </summary>
public LisReport Build() => new LisReport(this);
}
}
// 调用示例:
// var report = new LisReport.Builder("P20260926001", "CHECK001", "张医生")
// .WithResult("白细胞6.5")
// .WithReference("4-10×10^9/L")
// .WithRemark("结果正常")
// .Build();
2.6 原型模式
业务场景
LIS同类型检验报告批量生成、HIS相同模板医嘱快速复制,基于已有原型克隆修改。
使用原因
通过克隆原型快速创建相似对象,避免重复初始化,提升创建效率。
优缺点
✅ 对象创建高效、简化相似对象生成、保留原型状态
❌ 深拷贝实现复杂、对象包含引用类型需特殊处理
C# 实现
C#
/// <summary>
/// 检验报告原型接口
/// </summary>
public interface ILisReportPrototype
{
ILisReportPrototype Clone();
}
/// <summary>
/// 血常规报告原型
/// </summary>
public class BloodReportPrototype : ILisReportPrototype
{
public string CheckType { get; set; } = "血常规";
public string ReferenceRange { get; set; } = "白细胞:4-10,血小板:100-300";
public string PatientId { get; set; } = string.Empty;
public string Result { get; set; } = string.Empty;
/// <summary>
/// 浅拷贝原型
/// </summary>
public ILisReportPrototype Clone()
{
return (ILisReportPrototype)MemberwiseClone();
}
}
// 调用示例:
// var prototype = new BloodReportPrototype();
// var report1 = (BloodReportPrototype)prototype.Clone();
// report1.PatientId = "P001";
// report1.Result = "白细胞6.2";
三、结构型设计模式(全7种)
3.1 适配器模式
业务场景
LIS对接第三方检验设备(老旧生化仪、进口设备),不同厂商接口、数据格式不统一,通过适配器转换为系统标准接口。
使用原因
在不修改原有系统和第三方设备代码的前提下,完成异构接口兼容。
优缺点
✅ 兼容异构接口、解耦适配逻辑、符合开闭原则
❌ 增加适配层,调用链路变长
C# 实现
C#
/// <summary>
/// LIS系统标准设备接口
/// </summary>
public interface ILisDeviceStandard
{
/// <summary>
/// 读取标准格式检验数据
/// </summary>
string ReadStandardData();
}
/// <summary>
/// 第三方老旧生化仪(原生接口不兼容)
/// </summary>
public class OldBiochemicalDevice
{
/// <summary>
/// 厂商自有方法,返回原始格式数据
/// </summary>
public string GetRawData()
{
return "GLU:5.6|UA:320|CRE:78";
}
}
/// <summary>
/// 生化仪适配器:将老旧设备适配为系统标准接口
/// </summary>
public class BiochemicalDeviceAdapter : ILisDeviceStandard
{
private readonly OldBiochemicalDevice _oldDevice;
public BiochemicalDeviceAdapter(OldBiochemicalDevice oldDevice)
{
_oldDevice = oldDevice;
}
public string ReadStandardData()
{
var raw = _oldDevice.GetRawData();
// 数据格式转换、字段映射
return $"【LIS标准格式】{raw.Replace('|', ';')}";
}
}
3.2 装饰器模式
业务场景
HIS收费单打印:基础打印、医保章打印、诊断信息打印、费用明细打印,可灵活组合打印内容。
使用原因
动态扩展对象功能,替代多层继承,避免子类数量爆炸。
优缺点
✅ 功能组合灵活、比继承更轻量、符合开闭原则
❌ 多层装饰增加调试复杂度
C# 实现
C#
/// <summary>
/// 收费单打印接口
/// </summary>
public interface IReceiptPrinter
{
void Print();
}
/// <summary>
/// 基础收费单打印
/// </summary>
public class BaseReceiptPrinter : IReceiptPrinter
{
public void Print()
{
Console.WriteLine("打印基础收费单:患者信息、项目总金额");
}
}
/// <summary>
/// 打印装饰器基类
/// </summary>
public abstract class ReceiptDecorator : IReceiptPrinter
{
protected readonly IReceiptPrinter _printer;
protected ReceiptDecorator(IReceiptPrinter printer)
{
_printer = printer;
}
public abstract void Print();
}
/// <summary>
/// 医保章装饰器
/// </summary>
public class InsuranceStampDecorator : ReceiptDecorator
{
public InsuranceStampDecorator(IReceiptPrinter printer) : base(printer) { }
public override void Print()
{
_printer.Print();
Console.WriteLine("加盖医保结算专用章");
}
}
/// <summary>
/// 诊断信息装饰器
/// </summary>
public class DiagnosisDecorator : ReceiptDecorator
{
public DiagnosisDecorator(IReceiptPrinter printer) : base(printer) { }
public override void Print()
{
_printer.Print();
Console.WriteLine("打印诊断信息:ICD-10编码及诊断名称");
}
}
// 调用示例:
// IReceiptPrinter printer = new BaseReceiptPrinter();
// printer = new InsuranceStampDecorator(printer);
// printer = new DiagnosisDecorator(printer);
// printer.Print();
3.3 代理模式
业务场景
LIS检验结果访问代理:增加权限校验、访问日志、结果缓存,不修改真实数据访问类。
使用原因
在不改动目标对象的前提下,增加访问控制、日志、缓存等横切逻辑。
优缺点
✅ 保护目标对象、统一处理横切逻辑、职责分离
❌ 增加代理层,调用链路变长
C# 实现
C#
/// <summary>
/// 检验结果数据访问接口
/// </summary>
public interface ILisResultAccess
{
string GetResult(string patientId);
}
/// <summary>
/// 真实数据访问实现
/// </summary>
public class LisResultDataAccess : ILisResultAccess
{
public string GetResult(string patientId)
{
return $"患者{patientId}检验结果:各项指标正常";
}
}
/// <summary>
/// 数据访问代理:权限校验+日志记录
/// </summary>
public class LisResultAccessProxy : ILisResultAccess
{
private readonly LisResultDataAccess _realAccess;
private readonly string _currentUserRole;
public LisResultAccessProxy(LisResultDataAccess realAccess, string currentUserRole)
{
_realAccess = realAccess;
_currentUserRole = currentUserRole;
}
public string GetResult(string patientId)
{
// 权限校验
if (_currentUserRole is not "Doctor" and not "LabTechnician")
{
throw new UnauthorizedAccessException("无权限查看检验结果");
}
// 访问日志
Console.WriteLine($"[审计日志] 用户角色{_currentUserRole}查看患者{patientId}结果");
// 调用真实对象
return _realAccess.GetResult(patientId);
}
}
3.4 外观模式
业务场景
HIS出院结算:封装收费、医保结算、票据打印、病历归档多个子系统,对外提供统一结算入口。
使用原因
为复杂子系统提供统一高层接口,降低客户端调用复杂度,隔离子系统依赖。
优缺点
✅ 接口简洁、降低调用成本、隔离系统间依赖
❌ 外观类易膨胀,不符合开闭原则
C# 实现
C#
#region 子系统
/// <summary>
/// 收费子系统
/// </summary>
public class ChargeService
{
public void SettleCharge(decimal amount)
{
Console.WriteLine($"完成收费结算:{amount:F2}元");
}
}
/// <summary>
/// 医保结算子系统
/// </summary>
public class InsuranceService
{
public void SettleInsurance()
{
Console.WriteLine("完成医保统筹结算");
}
}
/// <summary>
/// 票据打印子系统
/// </summary>
public class ReceiptService
{
public void PrintReceipt()
{
Console.WriteLine("打印结算发票及费用明细");
}
}
/// <summary>
/// 病历归档子系统
/// </summary>
public class MedicalRecordService
{
public void ArchiveRecord(string patientId)
{
Console.WriteLine($"患者{patientId}病历完成归档");
}
}
#endregion
/// <summary>
/// 出院结算外观类:统一封装所有结算流程
/// </summary>
public class DischargeSettlementFacade
{
private readonly ChargeService _charge = new();
private readonly InsuranceService _insurance = new();
private readonly ReceiptService _receipt = new();
private readonly MedicalRecordService _record = new();
/// <summary>
/// 一站式出院结算
/// </summary>
public void Settle(string patientId, decimal amount)
{
_charge.SettleCharge(amount);
_insurance.SettleInsurance();
_receipt.PrintReceipt();
_record.ArchiveRecord(patientId);
}
}
3.5 组合模式
业务场景
HIS医嘱树形结构:医嘱组包含子医嘱、检验组合包含多个检验项目,支持树形层级管理。
使用原因
表示部分-整体的层级结构,统一处理单个对象和组合对象。
优缺点
✅ 树形结构清晰、节点扩展灵活、统一处理叶子和组合节点
❌ 限制类型设计复杂,易过度泛化
C# 实现
C#
/// <summary>
/// 医嘱组件抽象
/// </summary>
public abstract class OrderComponent
{
public string Name { get; protected set; }
protected OrderComponent(string name)
{
Name = name;
}
public abstract void Display(int depth = 0);
public abstract void Add(OrderComponent component);
public abstract void Remove(OrderComponent component);
}
/// <summary>
/// 叶子节点:具体检验项目
/// </summary>
public class CheckItemLeaf : OrderComponent
{
public CheckItemLeaf(string name) : base(name) { }
public override void Display(int depth = 0)
{
Console.WriteLine(new string('-', depth) + Name);
}
public override void Add(OrderComponent component)
{
throw new NotSupportedException("叶子节点不能添加子项");
}
public override void Remove(OrderComponent component)
{
throw new NotSupportedException("叶子节点不能删除子项");
}
}
/// <summary>
/// 组合节点:医嘱组
/// </summary>
public class OrderGroupComposite : OrderComponent
{
private readonly List<OrderComponent> _children = new();
public OrderGroupComposite(string name) : base(name) { }
public override void Add(OrderComponent component)
{
_children.Add(component);
}
public override void Remove(OrderComponent component)
{
_children.Remove(component);
}
public override void Display(int depth = 0)
{
Console.WriteLine(new string('-', depth) + "+ " + Name);
foreach (var child in _children)
{
child.Display(depth + 2);
}
}
}
// 调用示例:
// var group = new OrderGroupComposite("生化检验组合");
// group.Add(new CheckItemLeaf("血糖"));
// group.Add(new CheckItemLeaf("肌酐"));
// group.Display();
3.6 桥接模式
业务场景
HIS支付维度扩展:支付方式(微信、医保、现金)与支付终端(PC、自助机、移动端)两个独立维度变化。
使用原因
将抽象与实现分离,两个维度独立扩展,避免多层继承导致的类爆炸。
优缺点
✅ 多维度独立扩展、解耦抽象与实现、符合开闭原则
❌ 增加系统理解难度,需识别独立变化维度
C# 实现
C#
#region 实现维度:支付终端
/// <summary>
/// 支付终端接口
/// </summary>
public interface IPaymentTerminal
{
void ExecutePay(decimal amount);
}
/// <summary>
/// PC端终端
/// </summary>
public class PCTerminal : IPaymentTerminal
{
public void ExecutePay(decimal amount)
{
Console.Write($"[PC端] ");
}
}
/// <summary>
/// 自助机终端
/// </summary>
public class KioskTerminal : IPaymentTerminal
{
public void ExecutePay(decimal amount)
{
Console.Write($"[自助机] ");
}
}
#endregion
#region 抽象维度:支付方式
/// <summary>
/// 支付方式抽象类
/// </summary>
public abstract class PaymentMethod
{
protected IPaymentTerminal _terminal;
protected PaymentMethod(IPaymentTerminal terminal)
{
_terminal = terminal;
}
public abstract void Pay(decimal amount);
}
/// <summary>
/// 微信支付
/// </summary>
public class WechatPayMethod : PaymentMethod
{
public WechatPayMethod(IPaymentTerminal terminal) : base(terminal) { }
public override void Pay(decimal amount)
{
_terminal.ExecutePay(amount);
Console.WriteLine($"微信支付:{amount:F2}元");
}
}
/// <summary>
/// 医保支付
/// </summary>
public class InsurancePayMethod : PaymentMethod
{
public InsurancePayMethod(IPaymentTerminal terminal) : base(terminal) { }
public override void Pay(decimal amount)
{
_terminal.ExecutePay(amount);
Console.WriteLine($"医保支付:{amount:F2}元");
}
}
#endregion
// 调用示例:
// var pay = new WechatPayMethod(new KioskTerminal());
// pay.Pay(100m);
3.7 享元模式
业务场景
LIS检验项目字典缓存:大量检验申请复用项目基础信息(名称、参考值、价格),通过享元复用减少内存占用。
使用原因
系统存在大量细粒度对象,通过共享内部状态降低内存消耗。
优缺点
✅ 大幅减少对象数量、节省内存、提升性能
❌ 分离内部/外部状态,逻辑复杂度提升
C# 实现
C#
/// <summary>
/// 检验项目享元(内部状态:不变的基础信息)
/// </summary>
public class CheckItemFlyweight
{
// 内部状态:共享不变
public string ItemCode { get; }
public string ItemName { get; }
public string ReferenceRange { get; }
public decimal Price { get; }
public CheckItemFlyweight(string itemCode, string itemName, string referenceRange, decimal price)
{
ItemCode = itemCode;
ItemName = itemName;
ReferenceRange = referenceRange;
Price = price;
}
/// <summary>
/// 显示信息,外部状态(患者ID)传入
/// </summary>
public void Display(string patientId)
{
Console.WriteLine($"患者{patientId} - {ItemName}({ItemCode}) 参考值:{ReferenceRange} 价格:{Price:F2}");
}
}
/// <summary>
/// 检验项目享元工厂
/// </summary>
public class CheckItemFlyweightFactory
{
private readonly Dictionary<string, CheckItemFlyweight> _flyweights = new();
/// <summary>
/// 获取享元对象,不存在则创建
/// </summary>
public CheckItemFlyweight GetFlyweight(string itemCode)
{
if (!_flyweights.ContainsKey(itemCode))
{
// 模拟从数据库加载基础数据
_flyweights.Add(itemCode, new CheckItemFlyweight(
itemCode,
"白细胞计数",
"4-10×10^9/L",
15m
));
}
return _flyweights[itemCode];
}
}
四、行为型设计模式(全11种)
4.1 策略模式
业务场景
HIS费用计算:自费患者、医保患者、大病保险患者,计费报销规则不同。
使用原因
消除大量if/else分支,将不同算法独立封装,可动态切换。
优缺点
✅ 消除分支判断、算法独立扩展、易于单元测试
❌ 策略类增多,客户端需理解策略差异
C# 实现
C#
/// <summary>
/// 费用计算策略接口
/// </summary>
public interface ICostCalcStrategy
{
/// <summary>
/// 计算患者自付金额
/// </summary>
decimal CalculateSelfPay(decimal totalFee);
}
/// <summary>
/// 自费患者策略
/// </summary>
public class SelfPayStrategy : ICostCalcStrategy
{
public decimal CalculateSelfPay(decimal totalFee) => totalFee;
}
/// <summary>
/// 医保患者策略(报销70%)
/// </summary>
public class InsuranceStrategy : ICostCalcStrategy
{
public decimal CalculateSelfPay(decimal totalFee) => totalFee * 0.3m;
}
/// <summary>
/// 大病保险策略(报销90%)
{
public decimal CalculateSelfPay(decimal totalFee) => totalFee * 0.1m;
}
/// <summary>
/// 费用计算上下文
/// </summary>
public class CostCalculator
{
private ICostCalcStrategy _strategy;
public CostCalculator(ICostCalcStrategy strategy)
{
_strategy = strategy;
}
public void SetStrategy(ICostCalcStrategy strategy)
{
_strategy = strategy;
}
public decimal GetSelfPayAmount(decimal totalFee)
{
return _strategy.CalculateSelfPay(totalFee);
}
}
4.2 模板方法模式
业务场景
LIS检验报告审核流程:样本核对→结果校验→审核发布,不同检验类型步骤细节不同,但流程固定。
使用原因
固定流程骨架由父类定义,具体步骤由子类实现,避免流程代码重复。
优缺点
✅ 流程复用、代码结构清晰、符合开闭原则
❌ 继承关系增强,子类受父类约束
C# 实现
C#
/// <summary>
/// 检验报告审核模板
/// </summary>
public abstract class ReportAuditTemplate
{
/// <summary>
/// 审核流程模板方法(固定流程)
/// </summary>
public void Audit()
{
CheckSampleInfo();
VerifyResult();
if (NeedRecheck()) // 钩子方法
{
RecheckReminder();
}
PublishReport();
}
// 具体步骤:子类实现
protected abstract void CheckSampleInfo();
protected abstract void VerifyResult();
// 钩子方法:可选步骤,默认不复核
protected virtual bool NeedRecheck() => false;
protected virtual void RecheckReminder() { }
// 公共步骤:父类实现
private void PublishReport()
{
Console.WriteLine("发布检验报告");
}
}
/// <summary>
/// 血常规报告审核
/// </summary>
public class BloodRoutineAudit : ReportAuditTemplate
{
protected override void CheckSampleInfo()
{
Console.WriteLine("核对血常规样本条码、抗凝剂类型");
}
protected override void VerifyResult()
{
Console.WriteLine("校验血常规五分类结果是否在合理区间");
}
protected override bool NeedRecheck() => true;
protected override void RecheckReminder()
{
Console.WriteLine("提示:结果异常,建议人工复核");
}
}
4.3 观察者模式
业务场景
LIS检验结果录入完成后,自动通知医生工作站、患者消息中心、系统审计日志。
使用原因
发布者与订阅者解耦,新增通知渠道不修改核心录入逻辑,支持动态订阅。
优缺点
✅ 发布订阅解耦、支持动态增减观察者、符合单一职责
❌ 通知顺序不可控、大量观察者影响性能
C# 实现
C#
/// <summary>
/// 观察者接口
/// </summary>
public interface ILisResultObserver
{
void Update(string patientId, string result);
}
/// <summary>
/// 主题:检验结果发布器
/// </summary>
public class LisResultSubject
{
private readonly List<ILisResultObserver> _observers = new();
public void Attach(ILisResultObserver observer)
{
_observers.Add(observer);
}
public void Detach(ILisResultObserver observer)
{
_observers.Remove(observer);
}
/// <summary>
/// 结果发布,通知所有观察者
/// </summary>
public void Notify(string patientId, string result)
{
foreach (var observer in _observers)
{
observer.Update(patientId, result);
}
}
}
/// <summary>
/// 观察者:医生工作站
/// </summary>
public class DoctorStationObserver : ILisResultObserver
{
public void Update(string patientId, string result)
{
Console.WriteLine($"【医生工作站】患者{patientId}检验结果已更新:{result}");
}
}
/// <summary>
/// 观察者:审计日志
/// </summary>
public class AuditLogObserver : ILisResultObserver
{
public void Update(string patientId, string result)
{
Console.WriteLine($"【审计日志】记录患者{patientId}检验结果录入操作");
}
}
4.4 责任链模式
业务场景
HIS处方审批流程:医生开具→药师审核→主任审批(大额处方),逐级流转。
使用原因
请求沿链条传递,每个节点只处理自己职责范围内的请求,可动态组合审批链路。
优缺点
✅ 请求与处理解耦、链路灵活配置、新增节点方便
❌ 请求可能无人处理、链路调试复杂
C# 实现
C#
/// <summary>
/// 处方审批处理者抽象
/// </summary>
public abstract class PrescriptionApprovalHandler
{
protected PrescriptionApprovalHandler? _nextHandler;
public void SetNext(PrescriptionApprovalHandler next)
{
_nextHandler = next;
}
/// <summary>
/// 处理审批请求
/// </summary>
public abstract void Handle(decimal prescriptionAmount);
}
/// <summary>
/// 医生初审
/// </summary>
public class DoctorApproval : PrescriptionApprovalHandler
{
public override void Handle(decimal prescriptionAmount)
{
if (prescriptionAmount <= 500m)
{
Console.WriteLine($"医生初审通过,金额:{prescriptionAmount:F2}元");
return;
}
Console.WriteLine("医生初审通过,转交药师审核");
_nextHandler?.Handle(prescriptionAmount);
}
}
/// <summary>
/// 药师审核
/// </summary>
public class PharmacistApproval : PrescriptionApprovalHandler
{
public override void Handle(decimal prescriptionAmount)
{
if (prescriptionAmount <= 2000m)
{
Console.WriteLine($"药师审核通过,金额:{prescriptionAmount:F2}元");
return;
}
Console.WriteLine("药师审核通过,转交主任审批");
_nextHandler?.Handle(prescriptionAmount);
}
}
/// <summary>
/// 主任审批
/// </summary>
public class DirectorApproval : PrescriptionApprovalHandler
{
public override void Handle(decimal prescriptionAmount)
{
Console.WriteLine($"主任最终审批通过,金额:{prescriptionAmount:F2}元");
}
}
// 调用示例:
// var doctor = new DoctorApproval();
// var pharmacist = new PharmacistApproval();
// var director = new DirectorApproval();
// doctor.SetNext(pharmacist);
// pharmacist.SetNext(director);
// doctor.Handle(3000m);
4.5 状态模式
业务场景
LIS检验样本生命周期:待采集→已采集→检验中→已审核→已发布,不同状态行为不同。
使用原因
将状态与行为绑定,消除大量状态判断if/else,状态切换逻辑清晰。
优缺点
✅ 状态逻辑清晰、消除分支判断、扩展新状态方便
❌ 状态类增多、状态切换关系复杂
C# 实现
C#
/// <summary>
/// 样本状态接口
/// </summary>
public interface ISampleStatus
{
void Handle(LisSample sample);
}
/// <summary>
/// 检验样本上下文
/// </summary>
public class LisSample
{
public string SampleId { get; }
public ISampleStatus CurrentStatus { get; set; }
public LisSample(string sampleId)
{
SampleId = sampleId;
CurrentStatus = new WaitingCollectStatus(); // 初始状态
}
/// <summary>
/// 执行当前状态行为
/// </summary>
public void Process()
{
CurrentStatus.Handle(this);
}
}
/// <summary>
/// 待采集状态
/// </summary>
public class WaitingCollectStatus : ISampleStatus
{
public void Handle(LisSample sample)
{
Console.WriteLine($"样本{sample.SampleId}:待采集,等待护士采样");
// 状态切换示例:sample.CurrentStatus = new CollectedStatus();
}
}
/// <summary>
/// 检验中状态
/// </summary>
public class TestingStatus : ISampleStatus
{
public void Handle(LisSample sample)
{
Console.WriteLine($"样本{sample.SampleId}:检验中,设备正在分析");
}
}
/// <summary>
/// 已发布状态
/// </summary>
public class PublishedStatus : ISampleStatus
{
public void Handle(LisSample sample)
{
Console.WriteLine($"样本{sample.SampleId}:已发布报告,可查看");
}
}
4.6 命令模式
业务场景
HIS医嘱操作:开单、撤销、重做,将操作封装为命令对象,支持操作回滚与记录。
使用原因
将请求封装为对象,支持撤销、重做、操作日志、命令队列等功能。
优缺点
✅ 支持撤销/重做、命令可排队记录、请求与执行解耦
❌ 命令类膨胀,增加系统复杂度
C# 实现
C#
/// <summary>
/// 命令接口
/// </summary>
public interface IOrderCommand
{
void Execute();
void Undo();
}
/// <summary>
/// 医嘱接收者:真正执行业务
/// </summary>
public class OrderReceiver
{
public void CreateOrder(string orderName)
{
Console.WriteLine($"开具医嘱:{orderName}");
}
public void CancelOrder(string orderName)
{
Console.WriteLine($"撤销医嘱:{orderName}");
}
}
/// <summary>
/// 开具医嘱命令
/// </summary>
public class CreateOrderCommand : IOrderCommand
{
private readonly OrderReceiver _receiver;
private readonly string _orderName;
public CreateOrderCommand(OrderReceiver receiver, string orderName)
{
_receiver = receiver;
_orderName = orderName;
}
public void Execute()
{
_receiver.CreateOrder(_orderName);
}
public void Undo()
{
_receiver.CancelOrder(_orderName);
}
}
/// <summary>
/// 命令调用者
/// </summary>
public class OrderInvoker
{
private readonly Stack<IOrderCommand> _commandHistory = new();
public void ExecuteCommand(IOrderCommand command)
{
command.Execute();
_commandHistory.Push(command);
}
/// <summary>
/// 撤销上一步操作
/// </summary>
public void UndoLast()
{
if (_commandHistory.Any())
{
var command = _commandHistory.Pop();
command.Undo();
}
}
}
4.7 迭代器模式
业务场景
HIS患者就诊队列遍历:待诊、检查中、已完成不同集合,提供统一遍历方式。
使用原因
隔离集合内部实现,提供统一的遍历接口,不暴露内部存储结构。
优缺点
✅ 统一遍历接口、隔离集合内部实现、支持多种遍历方式
❌ 增加迭代器类,简单场景过度设计
C# 实现
C#
/// <summary>
/// 迭代器接口
/// </summary>
public interface IPatientIterator
{
bool HasNext();
Patient Next();
}
/// <summary>
/// 患者实体
/// </summary>
public class Patient
{
public string PatientId { get; set; }
public string Name { get; set; }
}
/// <summary>
/// 就诊队列聚合接口
/// </summary>
public interface IPatientCollection
{
IPatientIterator CreateIterator();
int Count { get; }
Patient this[int index] { get; }
}
/// <summary>
/// 待诊患者队列
/// </summary>
public class WaitingPatientCollection : IPatientCollection
{
private readonly List<Patient> _patients = new();
public int Count => _patients.Count;
public Patient this[int index] => _patients[index];
public void Add(Patient patient) => _patients.Add(patient);
public IPatientIterator CreateIterator()
{
return new PatientIterator(this);
}
}
/// <summary>
/// 具体迭代器
/// </summary>
public class PatientIterator : IPatientIterator
{
private readonly IPatientCollection _collection;
private int _index = 0;
public PatientIterator(IPatientCollection collection)
{
_collection = collection;
}
public bool HasNext()
{
return _index < _collection.Count;
}
public Patient Next()
{
return _collection[_index++];
}
}
4.8 中介者模式
业务场景
HIS科室间协作:门诊、检验、药房、收费通过中介者通信,不直接相互依赖。
使用原因
用中介者封装对象间交互,将网状依赖转为星型依赖,降低耦合。
优缺点
✅ 降低对象间耦合、集中管理交互、简化对象通信
❌ 中介者易膨胀,逻辑复杂后难以维护
C# 实现
C#
/// <summary>
/// 科室中介者接口
/// </summary>
public interface IDepartmentMediator
{
void SendMessage(string fromDept, string toDept, string message);
}
/// <summary>
/// 科室基类
/// </summary>
public abstract class DepartmentBase
{
protected readonly IDepartmentMediator _mediator;
public string DeptName { get; }
protected DepartmentBase(IDepartmentMediator mediator, string deptName)
{
_mediator = mediator;
DeptName = deptName;
}
public void Send(string toDept, string message)
{
_mediator.SendMessage(DeptName, toDept, message);
}
public abstract void Receive(string fromDept, string message);
}
/// <summary>
/// 门诊科室
/// </summary>
public class OutpatientDept : DepartmentBase
{
public OutpatientDept(IDepartmentMediator mediator) : base(mediator, "门诊") { }
public override void Receive(string fromDept, string message)
{
Console.WriteLine($"[门诊]收到{fromDept}消息:{message}");
}
}
/// <summary>
/// 检验科
/// </summary>
public class LabDept : DepartmentBase
{
public LabDept(IDepartmentMediator mediator) : base(mediator, "检验科") { }
public override void Receive(string fromDept, string message)
{
Console.WriteLine($"[检验科]收到{fromDept}消息:{message}");
}
}
/// <summary>
/// 医院中介者
/// </summary>
public class HospitalMediator : IDepartmentMediator
{
private readonly Dictionary<string, DepartmentBase> _departments = new();
public void Register(DepartmentBase dept)
{
_departments[dept.DeptName] = dept;
}
public void SendMessage(string fromDept, string toDept, string message)
{
if (_departments.TryGetValue(toDept, out var dept))
{
dept.Receive(fromDept, message);
}
}
}
4.9 备忘录模式
业务场景
LIS检验结果编辑:保存编辑前快照,支持撤销回退到历史版本。
使用原因
在不破坏封装的前提下,保存对象历史状态,支持回滚。
优缺点
✅ 提供状态回滚能力、不破坏原发器封装
❌ 保存多状态占用内存、状态过多管理复杂
C# 实现
C#
/// <summary>
/// 备忘录:保存检验结果状态
/// </summary>
public class LisResultMemento
{
public string ResultContent { get; }
public DateTime SaveTime { get; }
public LisResultMemento(string content)
{
ResultContent = content;
SaveTime = DateTime.Now;
}
}
/// <summary>
/// 原发器:检验结果编辑器
/// </summary>
public class LisResultEditor
{
public string Content { get; set; } = string.Empty;
/// <summary>
/// 创建备忘录
/// </summary>
public LisResultMemento Save()
{
return new LisResultMemento(Content);
}
/// <summary>
/// 恢复备忘录状态
/// </summary>
public void Restore(LisResultMemento memento)
{
Content = memento.ResultContent;
}
}
/// <summary>
/// 管理者:保存历史备忘录
/// </summary>
public class ResultHistoryCaretaker
{
private readonly Stack<LisResultMemento> _history = new();
public void SaveMemento(LisResultMemento memento)
{
_history.Push(memento);
}
/// <summary>
/// 获取上一个版本
/// </summary>
public LisResultMemento? GetLast()
{
return _history.Any() ? _history.Pop() : null;
}
}
// 调用示例:
// var editor = new LisResultEditor();
// var caretaker = new ResultHistoryCaretaker();
// editor.Content = "白细胞6.5";
// caretaker.SaveMemento(editor.Save());
// editor.Content = "白细胞7.2";
// editor.Restore(caretaker.GetLast()!); // 回退
4.10 访问者模式
业务场景
HIS报表统计:财务统计、科室统计、医保统计,不同统计方式访问相同医嘱数据。
使用原因
将数据结构与数据操作分离,新增操作不修改数据结构。
优缺点
✅ 操作扩展灵活、符合单一职责、集中相关操作
❌ 新增数据结构困难,依赖对象结构稳定
C# 实现
C#
/// <summary>
/// 访问者接口
/// </summary>
public interface IReportVisitor
{
void Visit(MedicineOrder order);
void Visit(CheckOrder order);
}
/// <summary>
/// 医嘱元素抽象
/// </summary>
public abstract class OrderElement
{
public decimal Amount { get; set; }
public abstract void Accept(IReportVisitor visitor);
}
/// <summary>
/// 药品医嘱
/// </summary>
public class MedicineOrder : OrderElement
{
public override void Accept(IReportVisitor visitor)
{
visitor.Visit(this);
}
}
/// <summary>
/// 检查医嘱
/// </summary>
public class CheckOrder : OrderElement
{
public override void Accept(IReportVisitor visitor)
{
visitor.Visit(this);
}
}
/// <summary>
/// 财务统计访问者
/// </summary>
public class FinanceVisitor : IReportVisitor
{
public decimal TotalIncome { get; private set; }
public void Visit(MedicineOrder order)
{
TotalIncome += order.Amount;
Console.WriteLine($"财务统计:药品收入{order.Amount:F2}元");
}
public void Visit(CheckOrder order)
{
TotalIncome += order.Amount;
Console.WriteLine($"财务统计:检查收入{order.Amount:F2}元");
}
}
/// <summary>
/// 医保统计访问者
/// </summary>
public class InsuranceVisitor : IReportVisitor
{
public void Visit(MedicineOrder order)
{
Console.WriteLine($"医保统计:药品费用{order.Amount:F2}元,纳入医保核算");
}
public void Visit(CheckOrder order)
{
Console.WriteLine($"医保统计:检查费用{order.Amount:F2}元,部分报销");
}
}
4.11 解释器模式
业务场景
LIS检验危急值规则解析:自定义规则表达式如白细胞>30 OR 血小板<50,解析并判断是否触发危急值。
使用原因
解析特定领域语言,灵活配置规则,无需硬编码判断逻辑。
优缺点
✅ 规则灵活可配置、易于扩展语法
❌ 复杂语法解析困难,执行效率较低
C# 实现
C#
/// <summary>
/// 表达式接口
/// </summary>
public interface IExpression
{
bool Interpret(Dictionary<string, decimal> context);
}
/// <summary>
/// 变量表达式
/// </summary>
public class VariableExpression : IExpression
{
private readonly string _variableName;
public VariableExpression(string variableName)
{
_variableName = variableName;
}
public bool Interpret(Dictionary<string, decimal> context)
{
return context.ContainsKey(_variableName);
}
public decimal GetValue(Dictionary<string, decimal> context)
{
return context[_variableName];
}
}
/// <summary>
/// 大于表达式
/// </summary>
public class GreaterThanExpression : IExpression
{
private readonly VariableExpression _left;
private readonly decimal _right;
public GreaterThanExpression(VariableExpression left, decimal right)
{
_left = left;
_right = right;
}
public bool Interpret(Dictionary<string, decimal> context)
{
return _left.GetValue(context) > _right;
}
}
/// <summary>
/// OR逻辑表达式
/// </summary>
public class OrExpression : IExpression
{
private readonly IExpression _left;
private readonly IExpression _right;
public OrExpression(IExpression left, IExpression right)
{
_left = left;
_right = right;
}
public bool Interpret(Dictionary<string, decimal> context)
{
return _left.Interpret(context) || _right.Interpret(context);
}
}
// 调用示例:规则:白细胞>30 OR 血小板<50
// var wbc = new VariableExpression("白细胞");
// var plt = new VariableExpression("血小板");
// var rule = new OrExpression(
// new GreaterThanExpression(wbc, 30),
// new LessThanExpression(plt, 50)
// );
// var context = new Dictionary<string, decimal> {{"白细胞", 35}, {"血小板", 120}};
// var isCritical = rule.Interpret(context); // true
五、设计模式选型速查表
| 业务场景 | 推荐模式 | 核心价值 |
|---|---|---|
| 全局唯一配置/资源 | 单例模式 | 全局唯一、节省资源 |
| 简单对象创建、类型固定 | 简单工厂 | 统一创建、代码简洁 |
| 多类型产品独立扩展 | 工厂方法 | 符合开闭、扩展灵活 |
| 产品族批量创建 | 抽象工厂 | 约束产品族一致性 |
| 复杂多字段对象构建 | 建造者模式 | 分步构建、参数灵活 |
| 相似对象快速复制 | 原型模式 | 提升创建效率 |
| 第三方设备/接口兼容 | 适配器模式 | 异构兼容、解耦适配 |
| 动态扩展功能、替代继承 | 装饰器模式 | 功能灵活组合 |
| 权限控制、日志、缓存 | 代理模式 | 横切逻辑统一处理 |
| 复杂子系统统一入口 | 外观模式 | 简化调用、隔离依赖 |
| 树形层级结构(医嘱/菜单) | 组合模式 | 统一处理整体与部分 |
| 多维度独立变化 | 桥接模式 | 解耦抽象与实现 |
| 大量细粒度对象复用 | 享元模式 | 节省内存、提升性能 |
| 多算法/规则切换 | 策略模式 | 消除分支、易于扩展 |
| 固定流程、步骤不同 | 模板方法 | 流程复用、骨架统一 |
| 事件多订阅通知 | 观察者模式 | 发布订阅解耦 |
| 逐级审批/流程链路 | 责任链模式 | 链路灵活、职责分离 |
| 状态驱动行为 | 状态模式 | 消除状态判断 |
| 操作撤销/重做/日志 | 命令模式 | 请求封装、支持回滚 |
| 集合统一遍历 | 迭代器模式 | 隔离内部实现 |
| 多对象交互通信 | 中介者模式 | 网状依赖转星型 |
| 状态历史回滚 | 备忘录模式 | 保存快照、支持撤销 |
| 数据结构固定、操作多变 | 访问者模式 | 操作与数据分离 |
| 领域规则解析 | 解释器模式 | 规则灵活配置 |
六、总结
设计模式的核心价值是解决业务变化带来的复杂度问题,而非为了模式而模式。
在HIS/LIS医疗系统中,建议遵循以下原则:
-
优先解决核心痛点:设备对接用适配器、收费规则用策略、审批流程用责任链
-
避免过度设计:简单场景优先简单实现,复杂度上升时再引入模式
-
团队共识优先:选用团队熟悉的模式,保证代码可维护性
-
结合.NET生态:可配合依赖注入、泛型、特性等特性优化模式实现
(注:部分内容由 AI 生成,仅供大家学习和参考)