设计模式
中介者模式是一种行为型设计模式,它允许将对象间的通信封装到一个中介对象中,从而使得对象间不再直接相互依赖。这种模式通过避免对象之间的显式引用来减少耦合,并且允许独立修改和重用各个对象。
模型说明
- 组件(Component)是各种包含业务逻辑的类。每个组件都有一个指向中介者的引用,该引用被声明为中介者接口类型。组件不知道中介者实际所属的类,因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
- 中介者(Mediator)接口声明了与组件交流的方法,但通常仅包括一个通知方法。组件可将任意上下文(包括自己的对象)作为该方法的参数,只有这样接收组件和发送者类之间才不会耦合。
- 具体中介者(Concrete Mediator)封装了多种组件间的关系。具体中介者通常会保存所有组件的引用并对其进行管理,甚至有时会对其生命周期进行管理。
- 组件并不知道其他组件的情况。如果组件内发生了重要事件,它只能通知中介者。中介者收到通知后能轻易地确定发送者,这或许已足以判断接下来需要触发的组件了。
- 对于组件来说,中介者看上去完全就是一个黑箱。发送者不知道最终会由谁来处理自己的请求,接收者也不知道最初是谁发出了请求。
优缺点
1.优点
- 单一职责原则:你可以将多个组件间的交流抽取到同一位置,使其更易于理解和维护。
- 开闭原则:你无需修改实际组件就能增加新的中介者。
- 你可以减轻应用中多个组件间的耦合情况。
- 你可以更方便地复用各个组件。
- 中介者模式的优点在于可以减少对象之间的耦合,从而使得系统更加灵活和可扩展。同时,由于所有的通信都是经过中介者对象的,因此可以更加方便地进行监控和管理。
2.缺点
- 一段时间后,中介者可能会演化成为上帝对象
使用场景
- 系统中存在大量的对象,并且它们之间存在复杂的关系。
- 系统中的对象需要频繁地进行通信,并且这些通信可能会随着时间的推移而发生变化。
- 系统需要支持动态的行为,例如添加或删除对象,或者改变它们之间的关系。
参考代码
火车站交通系统。两列火车互相之间从来不会就站台的空闲状态进行通信。
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:
PassengerTrain: Arrived FreightTrain: Arrival blocked, waiting PassengerTrain: Leaving FreightTrain: Arrival permitted FreightTrain: Arrived