行为设计模式——责任链模式

责任链(Chain of Responsibility)模式是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

以医院为例。在一个医院中会有如下职责成员:

  1. 挂号处
  2. 医生
  3. 收银处
  4. 药房

当病人来医院看病时,他会先去挂号处挂号,然后找医生看病,看完病后去收银处缴费,最后去药房拿药。在这个过程中,病人需要经过一个由四个职责部门组成的链条。病人在一个职责部门的事务结束后才能进入后续的职责部门,在这个过程中我们可以清晰地看到一条职责链。

现在可以说说责任链模式的适用场景了:

  • 当一个请求需要经过多个环节的处理时;
  • 因为有多个对象可以处理某个请求,但我们并不想让客户端选择处理请求的对象,同时我们还想将客户端和处理器解耦,此时我们可以选择职责链模式:客户端只需要和职责链中的第一个处理器接触就可以了。

代码示例:

package main

import (
	"fmt"
)

// 病人
type patient struct {
	name              string
	registrationDone  bool
	doctorCheckUpDone bool
	medicineDone      bool
	paymentDone       bool
}

// 医院部门接口
type department interface {
	execute(*patient)
	setNext(department)
}

// 挂号处
type reception struct {
	next department
}

func (r *reception) execute(p *patient) {
	if p.registrationDone {
		fmt.Println("Patient registration already done")
		r.next.execute(p)
		return
	}
	fmt.Println("Reception registering patient")
	p.registrationDone = true
	if r.next != nil {
		r.next.execute(p)
	}
}

func (r *reception) setNext(next department) {
	r.next = next
}

// 医生
type doctor struct {
	next department
}

func (d *doctor) execute(p *patient) {
	if p.doctorCheckUpDone {
		fmt.Println("Doctor checkup already done")
		d.next.execute(p)
		return
	}
	fmt.Println("Doctor checking patient")
	p.doctorCheckUpDone = true
	if d.next != nil {
		d.next.execute(p)
	}
}

func (d *doctor) setNext(next department) {
	d.next = next
}

// 收银处
type cashier struct {
	next department
}

func (c *cashier) execute(p *patient) {
	if p.paymentDone {
		fmt.Println("Payment Done")
	}
	fmt.Println("Cashier getting money from patient patient")
	p.paymentDone = true
	if c.next != nil {
		c.next.execute(p)
	}
}

func (c *cashier) setNext(next department) {
	c.next = next
}

// 药房
type medical struct {
	next department
}

func (m *medical) execute(p *patient) {
	if p.medicineDone {
		fmt.Println("Medicine already given to patient")
		m.next.execute(p)
		return
	}
	fmt.Println("Medical giving medicine to patient")
	p.medicineDone = true
	if m.next != nil {
		m.next.execute(p)
	}
}

func (m *medical) setNext(next department) {
	m.next = next
}

func main() {

	reception := &reception{}
	doctor := &doctor{}
	cashier := &cashier{}
	medical := &medical{}

	//Set next for reception department
	reception.setNext(doctor)

	//Set next for doctor department
	doctor.setNext(cashier)

	//Set next for cashier department
	cashier.setNext(medical)

	//Patient visiting
	patient := &patient{name: "abc"}
	fmt.Printf("patient:%+v", patient)
	reception.execute(patient)
	fmt.Printf("patient:%+v", patient)
}

运行代码,输出结果:

patient:&{name:abc registrationDone:false doctorCheckUpDone:false medicineDone:false paymentDone:false}Reception registering patient
Doctor checking patient
Cashier getting money from patient patient
Medical giving medicine to patient
patient:&{name:abc registrationDone:true doctorCheckUpDone:true medicineDone:true paymentDone:true}

也可以看看


全国大流量卡免费领

19元月租ㆍ超值优惠ㆍ长期套餐ㆍ免费包邮ㆍ官方正品