GoLang設計模式07 - 責任鏈模式


責任鏈模式是一種行為型設計模式。在這種模式中,會為請求創建一條由多個Handler組成的鏈路。每一個進入的請求,都會經過這條鏈路。這條鏈路上的Handler可以選擇如下操作:

  • 處理請求或跳過處理
  • 決定是否將請求傳給這條鏈路上的下一個Handler

下面是責任鏈模式的用例圖:

關於責任鏈模式的用途最好還是用個案例來說明下。

以醫院為例。在一個醫院中會有如下職責成員:

  1. 掛號處
  2. 醫生
  3. 收銀處
  4. 葯房

當病人來醫院看病時,他會先去掛號處掛號,然后找醫生看病,看完病后去收銀處繳費,最后去葯房拿葯。在這個過程中,病人需要經過一個由四個職責部門組成的鏈條。病人在一個職責部門的事務結束后才能進入后續的職責部門,在這個過程中我們可以清晰地看到一條職責鏈。

現在可以說說責任鏈模式的適用場景了:

  1. 當一個請求需要經過多個環節的處理時;
  2. 因為有多個對象可以處理某個請求,但我們並不想讓客戶端選擇處理請求的對象,同時我們還想將客戶端和處理器解耦,此時我們可以選擇職責鏈模式:客戶端只需要和職責鏈中的第一個處理器接觸就可以了。

下面是病人到醫院看病這個實例的類圖:

 實現代碼如下:

department.go

type department interface {
	execute(*patient)
	setNext(department)
}

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")
		m.next.execute(p)
		return
	}
	fmt.Println("Medical giving medicine to patient")
	p.medicineDone = true
	m.next.execute(p)
}

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")
	}
	fmt.Println("Cashier getting money from patient patient")
	c.next.execute(p)
}

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

doctor.go

import "fmt"

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
	d.next.execute(p)
}

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

reception.go

import "fmt"

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
	r.next.execute(p)
}

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

patient.go

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

  main.go

func main() {

	medical := &medical{}

	//Set next for cashier department
	cashier := &cashier{}
	cashier.setNext(medical)
	//Set next for doctor department
	doctor := &doctor{}
	doctor.setNext(cashier)
	//Set next for reception department
	reception := &reception{}
	reception.setNext(doctor)

	patient := &patient{name: "abc"}
	//Patient visiting
	reception.execute(patient)
}

執行結果如下:

Reception registering patient
Doctor checking patient
Cashier getting money from patient patient
Medical giving medicine to patient

代碼已上傳至GitHub:zhyea / go-patterns / Chain of Responsibility Design Pattern

END!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM