中介者模式是一种行为设计模式。此模式是创建一个中介对象,以防止对象之间的直接交互,从而避免它们之间的直接依赖关系。
一个很好的中介模式的例子是铁路系统平台,两列火车之间是相互独立的,站长充当调停者,使站台仅对其中一列列车可用。列车通过站长交互,站长维持着等候火车的队列,当任何一辆列车离开站台时,通知下一辆列车可以进入了。
注意在下面的代码中,站长是如何充当火车和站台之间的中间人。
- 旅客列车(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