148 lines
3.8 KiB
Go
148 lines
3.8 KiB
Go
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) // 然后继续责任链
|
|
}
|