From 899772115c7d112993cb732ca821fdac1a6f723a Mon Sep 17 00:00:00 2001 From: fantasticbin Date: Sat, 5 Jul 2025 19:57:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=B4=A3=E4=BB=BB=E9=93=BE?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chain/chain.go | 147 ++++++++++++++++++++++++++++++++++++++++++++ chain/chain_test.go | 33 ++++++++++ 2 files changed, 180 insertions(+) create mode 100644 chain/chain.go create mode 100644 chain/chain_test.go diff --git a/chain/chain.go b/chain/chain.go new file mode 100644 index 0000000..01f62a7 --- /dev/null +++ b/chain/chain.go @@ -0,0 +1,147 @@ +package chain + +import ( + "errors" + "fmt" +) + +const ( + PatientStatusStart = iota + 1 // 状态:开始看病 + PatientStatusReception // 状态:已挂号 + PatientStatusClinic // 状态:已看诊 + PatientStatusCashier // 状态:已缴费 + PatientStatusPharmacy // 状态:已拿药 +) + +type Patient struct { + name string // 姓名 + status int // 状态 +} + +type PatientHandler interface { + Execute(patient *Patient) error // 处理链路传递 + SetNext(handler PatientHandler) PatientHandler // 设置下一个处理者 + Do(patient *Patient) error // 执行处理逻辑 +} + +// BaseHandler 充当抽象类的角色 +// Do 方法无法抽象出来,故不实现 +type BaseHandler struct { + nextHandler PatientHandler // 下一个处理者 +} + +func (h *BaseHandler) Execute(patient *Patient) error { + if patient == nil { + return nil + } + + // 因为 Do 方法未实现,这里无法调用自身的 Do + // 实际调用链路时,需要为初始流程定义一个起始执行者 + + if h.nextHandler != nil { + if err := h.nextHandler.Do(patient); err != nil { // 调用下一个处理者的Do方法 + return err + } + return h.nextHandler.Execute(patient) // 调用下一个处理者的Execute方法 + } + + return nil +} + +func (h *BaseHandler) SetNext(handler PatientHandler) PatientHandler { + h.nextHandler = handler + return handler +} + +type Reception struct { + BaseHandler // 嵌入BaseHandler以实现链式调用 +} + +func (r *Reception) Do(patient *Patient) error { + if patient.status > PatientStatusStart { + return errors.New("患者已经挂号") + } + + fmt.Printf("挂号处为患者 %s 挂号\n", patient.name) + patient.status = PatientStatusReception // 更新患者状态为已挂号 + return nil +} + +type Clinic struct { + BaseHandler // 嵌入BaseHandler以实现链式调用 +} + +func (c *Clinic) Do(patient *Patient) error { + if patient.status == PatientStatusStart { + return errors.New("患者还未挂号") + } + + if patient.status > PatientStatusReception { + return errors.New("患者已经完成医生诊断") + } + + fmt.Printf("医生为患者 %s 进行诊断\n", patient.name) + patient.status = PatientStatusClinic // 更新患者状态为已看诊 + return nil +} + +type Cashier struct { + BaseHandler // 嵌入BaseHandler以实现链式调用 +} + +func (c *Cashier) Do(patient *Patient) error { + if patient.status < PatientStatusClinic { + return errors.New("患者还未看诊") + } + + if patient.status > PatientStatusClinic { + return errors.New("患者已经完成缴费") + } + + fmt.Printf("收费处收取患者 %s 的费用\n", patient.name) + patient.status = PatientStatusCashier // 更新患者状态为已缴费 + return nil +} + +type Pharmacy struct { + BaseHandler // 嵌入BaseHandler以实现链式调用 +} + +func (p *Pharmacy) Do(patient *Patient) error { + if patient.status < PatientStatusCashier { + return errors.New("患者还未缴费") + } + + if patient.status > PatientStatusCashier { + return errors.New("患者已经领取药物") + } + + fmt.Printf("药房为患者 %s 配药\n", patient.name) + patient.status = PatientStatusPharmacy // 更新患者状态为已拿药 + return nil +} + +type HospitalChainHandler struct { + BaseHandler // 嵌入BaseHandler以实现链式调用 +} + +// Do 该方法可无逻辑,如需执行逻辑则需要重写 Execute 来确保执行 +func (h *HospitalChainHandler) Do(patient *Patient) error { + fmt.Printf("患者 %s 开始看病\n", patient.name) + patient.status = PatientStatusStart // 更新患者状态为开始看病 + + return nil +} + +// Execute 重写该方法以确保责任链的执行顺序 +func (h *HospitalChainHandler) Execute(patient *Patient) error { + if patient == nil { + return nil + } + + if err := h.Do(patient); err != nil { // 首先执行自己的Do方法 + return err + } + + return h.BaseHandler.Execute(patient) // 然后继续责任链 +} diff --git a/chain/chain_test.go b/chain/chain_test.go new file mode 100644 index 0000000..e5e0245 --- /dev/null +++ b/chain/chain_test.go @@ -0,0 +1,33 @@ +package chain + +import "testing" + +func TestChain(t *testing.T) { + // 创建患者实例 + patient := &Patient{name: "张三"} + + // 创建看病处理者链 + hospital := &HospitalChainHandler{} + + // 设置病人看病的链路 + processes := []PatientHandler{ + &Reception{}, + &Clinic{}, + &Cashier{}, + &Pharmacy{}, + } + var current PatientHandler = hospital + for _, process := range processes { + current = current.SetNext(process) + } + + // 执行处理链 + if err := hospital.Execute(patient); err != nil { + t.Errorf("处理患者失败: %v", err) + } + + // 检查最终状态 + if patient.status != PatientStatusPharmacy { + t.Errorf("患者状态不正确,期望 %d,实际 %d", PatientStatusPharmacy, patient.status) + } +}