1. 程式人生 > 其它 >golang 中介者模式

golang 中介者模式

技術標籤:golang

中介者模式是一種行為設計模式。此模式是建立一箇中介物件,以防止物件之間的直接互動,從而避免它們之間的直接依賴關係。

一個很好的中介模式的例子是鐵路系統平臺,兩列火車之間是相互獨立的,站長充當調停者,使站臺僅對其中一列列車可用。列車通過站長互動,站長維持著等候火車的佇列,當任何一輛列車離開站臺時,通知下一輛列車可以進入了。

注意在下面的程式碼中,站長是如何充當火車和站臺之間的中間人。

  • 旅客列車(passengerTrain)和貨物列表(goodsTrain)實現了列車介面
  • 站長(stationManger)實現了中介者(mediator )介面

程式碼:

package main

import (
	"fmt"
	"sync"
)

func main() {
	stationManager := newStationManger()
	passengerTrain := &passengerTrain{
		name:     fmt.Sprintf("passengerTrain%d", 1),
		mediator: stationManager,
	}

	goodsTrain := &goodsTrain{
		name:     fmt.Sprintf("goodsTrain%d", 1),
		mediator: stationManager,
	}

	passengerTrain.requestArrival()
	goodsTrain.requestArrival()
	passengerTrain.departure()

	fmt.Println("exit")
}

type mediator interface {
	canLand(train) bool
	isLanded(train) bool
	notifyFree()
}

// 列車介面
type train interface {
	requestArrival() // 請求到達
	departure()      // 離開
	permitArrival()  // 批准進入
}

// 旅客列車
type passengerTrain struct {
	name     string
	mediator mediator
}

func (g *passengerTrain) requestArrival() {
	if g.mediator.canLand(g) {
		fmt.Println(g.name + ": Landing")
	} else {
		fmt.Println(g.name + ": Waiting")
	}
}

func (g *passengerTrain) departure() {
	fmt.Println(g.name + ": Leaving")
	g.mediator.notifyFree()
}

func (g *passengerTrain) permitArrival() {
	fmt.Println(g.name + ": Arrival Permitted. Landing")
}

// 貨物列車
type goodsTrain struct {
	name     string
	mediator mediator
}

func (g *goodsTrain) requestArrival() {
	if g.mediator.canLand(g) {
		fmt.Println(g.name + ": Landing")
	} else {
		fmt.Println(g.name + ": Waiting")
	}
}

func (g *goodsTrain) departure() {
	g.mediator.notifyFree()
	fmt.Println(g.name + ": Leaving")
}

func (g *goodsTrain) permitArrival() {
	fmt.Println(g.name + ": Arrival Permitted. Landing")
}

// 站長
type stationManager struct {
	isPlatformFree bool
	lock           *sync.Mutex
	trainQueue     []train
}

func newStationManger() *stationManager {
	return &stationManager{
		isPlatformFree: true,
		lock:           &sync.Mutex{},
	}
}

func (s *stationManager) canLand(t train) bool {
	s.lock.Lock()
	defer s.lock.Unlock()
	if s.isPlatformFree {
		s.isPlatformFree = false
		return true
	}
	s.trainQueue = append(s.trainQueue, t)
	return false
}

func (s *stationManager) isLanded(t train) bool {
	s.lock.Lock()
	defer s.lock.Unlock()
	for _, item := range s.trainQueue {
		if t == item {
			return true
		}
	}
	return false
}

func (s *stationManager) notifyFree() {
	s.lock.Lock()
	defer s.lock.Unlock()
	if !s.isPlatformFree {
		s.isPlatformFree = true
	}
	if len(s.trainQueue) > 0 {
		firstTrainInQueue := s.trainQueue[0]
		s.trainQueue = s.trainQueue[1:]
		firstTrainInQueue.permitArrival()
	}
}

輸出:

passengerTrain1: Landing
goodsTrain1: Waiting
passengerTrain1: Leaving
goodsTrain1: Arrival Permitted. Landing
exit