Привіт! Я знизив ціни на усі продукти. Час разом готувати свої програмерські скіли до пост-COVID-ної ери. Перевірити »
Посередник

Посередник на Go

Посередник — це поведінковий патерн, який спрощує комунікацію між компонентами системи.

Посередник прибирає прямі зв’язки між окремими компонентами, змушуючи їх спілкуватися один з одним через себе.

Концептуальний приклад

Система трафіку на залізничній платформі — чудовий приклад патерну Посередник. Два потяги ніколи не конфліктують між собою за наявність вільної платформи, натомість менеджер станції stationManager виступає посередником, який оголошує платформу вільною лише для одного потяга, а решту тримає у черзі. Коли поїзд відправляється зі станції, він сповіщає менеджера, що дає змогу прибути наступному в черзі поїзду.

train.go: Компонент

package main

type Train interface {
	arrive()
	depart()
	permitArrival()
}

passengerTrain.go: Конкретний компонент

package main

import "fmt"

type PassengerTrain struct {
	mediator Mediator
}

func (g *PassengerTrain) arrive() {
	if !g.mediator.canArrive(g) {
		fmt.Println("PassengerTrain: Arrival blocked, waiting")
		return
	}
	fmt.Println("PassengerTrain: Arrived")
}

func (g *PassengerTrain) depart() {
	fmt.Println("PassengerTrain: Leaving")
	g.mediator.notifyAboutDeparture()
}

func (g *PassengerTrain) permitArrival() {
	fmt.Println("PassengerTrain: Arrival permitted, arriving")
	g.arrive()
}

freightTrain.go: Конкретний компонент

package main

import "fmt"

type FreightTrain struct {
	mediator Mediator
}

func (g *FreightTrain) arrive() {
	if !g.mediator.canArrive(g) {
		fmt.Println("FreightTrain: Arrival blocked, waiting")
		return
	}
	fmt.Println("FreightTrain: Arrived")
}

func (g *FreightTrain) depart() {
	fmt.Println("FreightTrain: Leaving")
	g.mediator.notifyAboutDeparture()
}

func (g *FreightTrain) permitArrival() {
	fmt.Println("FreightTrain: Arrival permitted")
	g.arrive()
}

mediator.go: Інтерфейс посередника

package main

type Mediator interface {
	canArrive(Train) bool
	notifyAboutDeparture()
}

stationManager.go: Конкретний посередник

package main

type StationManager struct {
	isPlatformFree bool
	trainQueue     []Train
}

func newStationManger() *StationManager {
	return &StationManager{
		isPlatformFree: true,
	}
}

func (s *StationManager) canArrive(t Train) bool {
	if s.isPlatformFree {
		s.isPlatformFree = false
		return true
	}
	s.trainQueue = append(s.trainQueue, t)
	return false
}

func (s *StationManager) notifyAboutDeparture() {
	if !s.isPlatformFree {
		s.isPlatformFree = true
	}
	if len(s.trainQueue) > 0 {
		firstTrainInQueue := s.trainQueue[0]
		s.trainQueue = s.trainQueue[1:]
		firstTrainInQueue.permitArrival()
	}
}

main.go: Клієнтський код

package main

func main() {
	stationManager := newStationManger()

	passengerTrain := &PassengerTrain{
		mediator: stationManager,
	}
	freightTrain := &FreightTrain{
		mediator: stationManager,
	}

	passengerTrain.arrive()
	freightTrain.arrive()
	passengerTrain.depart()
}

output.txt: Результат виконання

PassengerTrain: Arrived
FreightTrain: Arrival blocked, waiting
PassengerTrain: Leaving
FreightTrain: Arrival permitted
FreightTrain: Arrived
На основі: Golang By Example

Посередник іншими мовами програмування

Посередник на C# Посередник на C++ Посередник на Java Посередник на PHP Посередник на Python Посередник на Ruby Посередник на Rust Посередник на Swift Посередник на TypeScript