GoLang设计模式08 - 责任链模式(行为型)
责任链模式是一种行为型设计模式。在这种模式中,会为请求创建一条由多个Handler组成的链路。每一个进入的请求,都会经过这条链路。这条链路上的Handler可以选择如下操作:
- 处理请求或跳过处理
- 决定是否将请求传给这条链路上的下一个Handler
下面是责任链模式的用例图:

关于责任链模式的用途最好还是用个案例来说明下。
以医院为例。在一个医院中会有如下职责成员:
- 挂号处
- 医生
- 收银处
- 药房
当病人来医院看病时,他会先去挂号处挂号,然后找医生看病,看完病后去收银处缴费,最后去药房拿药。在这个过程中,病人需要经过一个由四个职责部门组成的链条。病人在一个职责部门的事务结束后才能进入后续的职责部门,在这个过程中我们可以清晰地看到一条职责链。
现在可以说说责任链模式的适用场景了:
- 当一个请求需要经过多个环节的处理时;
- 因为有多个对象可以处理某个请求,但我们并不想让客户端选择处理请求的对象,同时我们还想将客户端和处理器解耦,此时我们可以选择职责链模式:客户端只需要和职责链中的第一个处理器接触就可以了。
下面是病人到医院看病这个实例的类图:

实现代码如下:
patient.go 病人
type patient struct { name string registrationDone bool //挂号 doctorCheckUpDone bool //就诊 medicineDone bool //取药 paymentDone bool //缴费 }
department.go 抽象层
1 type department interface { 2 execute(*patient) 3 setNext(department) 4 }
medical.go 取药
import "fmt" type medical struct { next department } func (m *medical) execute(p *patient) { if p.medicineDone { fmt.Println("Medicine already given to patient") return } fmt.Println("Medical giving medicine to patient") p.medicineDone = true } func (m *medical) setNext(next department) { m.next = next }
cashier.go 缴费
import "fmt" type cashier struct { next department } func (c *cashier) execute(p *patient) { if p.paymentDone { fmt.Println("Payment Done") c.next.execute(p) return } fmt.Println("Cashier getting money from patient patient") c.next.execute(p) } func (c *cashier) setNext(next department) { c.next = next }
doctor.go 就诊
1 import "fmt" 2 3 type doctor struct { 4 next department 5 } 6 7 func (d *doctor) execute(p *patient) { 8 if p.doctorCheckUpDone { 9 fmt.Println("Doctor checkup already done") 10 d.next.execute(p) 11 return 12 } 13 fmt.Println("Doctor checking patient") 14 p.doctorCheckUpDone = true 15 d.next.execute(p) 16 } 17 18 func (d *doctor) setNext(next department) { 19 d.next = next 20 }
reception.go 挂号
1 import "fmt" 2 3 type reception struct { 4 next department 5 } 6 7 func (r *reception) execute(p *patient) { 8 if p.registrationDone { 9 fmt.Println("Patient registration already done") 10 r.next.execute(p) 11 return 12 } 13 fmt.Println("Reception registering patient") 14 p.registrationDone = true 15 r.next.execute(p) 16 } 17 18 func (r *reception) setNext(next department) { 19 r.next = next 20 }
main.go
1 func main() { 2 3 medical := &medical{} 4 5 //Set next for cashier department 6 cashier := &cashier{} 7 cashier.setNext(medical) 8 //Set next for doctor department 9 doctor := &doctor{} 10 doctor.setNext(cashier) 11 //Set next for reception department 12 reception := &reception{} 13 reception.setNext(doctor) 14 15 patient := &patient{name: "abc"} 16 //Patient visiting 17 reception.execute(patient) 18 }
执行结果如下:
1 Reception registering patient 2 Doctor checking patient 3 Cashier getting money from patient patient 4 Medical giving medicine to patient
浙公网安备 33010602011771号