SOLDES de printemps
Médiateur

Médiateur en Go

Le Médiateur est un patron de conception comportemental qui diminue le couplage entre les composants d’un programme, en les faisant communiquer indirectement, via un objet médiateur spécial.

Le médiateur rend la modification, l’extension et la réutilisation de composants individuels aisées, car ils ne dépendent plus d’une dizaine de classes.

Exemple conceptuel

Le poste d’aiguillage d’une gare est un excellent exemple du patron de conception médiateur. Deux trains ne communiquent jamais ensemble pour connaître la disponibilité d’une plateforme. Le stationManager agit comme un médiateur : il n’autorise qu’un seul train à accéder à la plateforme et place les autres dans une file d’attente. Un train qui part va envoyer une notification au poste, ce qui permet au prochain train dans la file d’accéder à la plateforme.

train.go: Composant

package main

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

passengerTrain.go: Composant concret

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: Composant concret

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: Interface médiateur

package main

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

stationManager.go: Médiateur concret

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: Code client

package main

func main() {
	stationManager := newStationManger()

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

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

output.txt: Résultat de l’exécution

PassengerTrain: Arrived
FreightTrain: Arrival blocked, waiting
PassengerTrain: Leaving
FreightTrain: Arrival permitted
FreightTrain: Arrived

Médiateur dans les autres langues

Médiateur en C# Médiateur en C++ Médiateur en Java Médiateur en PHP Médiateur en Python Médiateur en Ruby Médiateur en Rust Médiateur en Swift Médiateur en TypeScript