Friend spotlight!
Whimsical Animations course
Friend spotlight!
NEW Whimsical Animations course
Friend spotlight! NEW Whimsical Animations course
huge discount only this week
Friend spotlight! Want to make your project stand out? NEW Whimsical Animations course huge discount only this week
Łańcuch zobowiązań

Łańcuch zobowiązań w języku Go

Łańcuch zobowiązań to behawioralny wzorzec projektowy pozwalający przekazywać żądanie wzdłuż łańcucha potencjalnych obiektów obsługujących aż zostanie obsłużone.

W łańcuchu zobowiązań wiele obiektów może obsłużyć żądanie bez konieczności sprzęgania klas wysyłających je z konkretnymi klasami odbierającymi. Łańcuch można układać dynamicznie w trakcie działania programu z dowolnych obiektów obsługujących, wyposażonych w standardowy interfejs obsługi żądań.

Przykład koncepcyjny

Popatrzmy na wzorzec Łańcuch Zobowiązań przez pryzmat przykładu opartego na aplikacji do obsługi szpitala. Szpital może mieć wiele oddziałów:

  • Recepcja
  • Lekarz
  • Gabinet zabiegowy
  • Kasa

Każdy nowy pacjent najpierw jest przyjmowany w Recepcji, następnie przez Lekarza, potem udaje się do Gabinetu Zabiegowego, a na końcu do Kasy (i tak dalej). Pacjent pokonuje więc pewien łańcuch oddziałów, gdzie każdy z nich kieruje go dalej po wypełnieniu swojej funkcji.

Wzorzec można zastosować gdy mamy do czynienia z wieloma kandydatami do przetworzenia tego samego żądania oraz gdy nie chcemy, aby klient wybierał odbiorcę samodzielnie, gdyż wiele obiektów może obsłużyć jego żądanie. Dzięki temu unikamy też sprzężenia klienta z odbiorcami. Klient musi wiedzieć tylko o pierwszym ogniwie łańcucha.

Jak w przykładzie ze szpitalem, pacjent najpierw kieruje się do recepcji. Następnie, na podstawie określonego stanu pacjenta jest wysyłany do stosownego obsługującego w łańcuchu.

department.go: Interfejs obsługującego

package main

type Department interface {
	execute(*Patient)
	setNext(Department)
}

reception.go: Konkretny obsługujący

package main

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
}

doctor.go: Konkretny obsługujący

package main

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
}

medical.go: Konkretny obsługujący

package main

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: Konkretny obsługujący

package main

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")
}

func (c *Cashier) setNext(next Department) {
	c.next = next
}

patient.go

package main

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

main.go: Kod klienta

package main

func main() {

	cashier := &Cashier{}

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

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

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

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

output.txt: Wynik działania

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

Łańcuch zobowiązań w innych językach

Łańcuch zobowiązań w języku C# Łańcuch zobowiązań w języku C++ Łańcuch zobowiązań w języku Java Łańcuch zobowiązań w języku PHP Łańcuch zobowiązań w języku Python Łańcuch zobowiązań w języku Ruby Łańcuch zobowiązań w języku Rust Łańcuch zobowiązań w języku Swift Łańcuch zobowiązań w języku TypeScript