golang 中介者模式

golang 中介者模式



前言

一、中介者模式是什么?

中介者模式是一种行为设计模式,能让你减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作,将网状依赖变为星状依赖。

中介者能使得程序更易于修改和扩展,而且能更方便地对独立的组件进行复用,因为它们不再依赖于很多其他的类。

中介者模式与观察者模式之间的区别是,中介者模式解决的是同类或者不同类的多个对象之间多对多的依赖关系,观察者模式解决的是多个对象与一个对象之间的多对一的依赖关系。

二、示例

机场塔台调度系统是一个体现中介者模式的典型示例,假设是一个小机场,每次只能同时允许一架飞机起降,每架靠近机场的飞机需要先与塔台沟通是否可以降落,如果没有空闲的跑道,需要在天空盘旋等待,如果有飞机离港,等待的飞机会收到塔台的通知,按先后顺序降落;这种方式,免去多架飞机同时到达机场需要相互沟通降落顺序的复杂性,减少多个飞机间的依赖关系,简化业务逻辑,从而降低系统出问题的风险。

1. channel 版本

channel 版本利用生产者和消费者模式最优,也可以改成多生产者、多消费者模式
airline.go

package mediator

import (
	"fmt"
	"sync"
	"time"
)

// Aircraft 飞机接口
type Aircraft interface {
	ApproachAirport(wg *sync.WaitGroup) // 抵达机场空域
	DepartAirport(wg *sync.WaitGroup)   // 飞离机场
}

// airliner 客机
type airliner struct {
	name            string          // 客机型号
	airportMediator AirportMediator // 机场调度
}

// NewAirliner 根据指定型号及机场调度创建客机
func NewAirliner(name string, mediator AirportMediator) *airliner {
	return &airliner{
		name:            name,
		airportMediator: mediator,
	}
}

func (a *airliner) ApproachAirport(wg *sync.WaitGroup) {
	a.airportMediator.CanLandAirport(a)
	fmt.Printf("客机%s成功滑翔降落机场;\n", a.name)
	wg.Done()
}

func (a *airliner) DepartAirport(wg *sync.WaitGroup) {
	time.Sleep(1 * time.Second)
	fmt.Printf("客机%s成功滑翔起飞,离开机场;\n", a.name)
	a.airportMediator.NotifyWaitingAircraft() // 通知等待的其他飞机
	wg.Done()
}

// helicopter 直升机
type helicopter struct {
	name            string
	airportMediator AirportMediator
}

// NewHelicopter 根据指定型号及机场调度创建直升机
func NewHelicopter(name string, mediator AirportMediator) *helicopter {
	return &helicopter{
		name:            name,
		airportMediator: mediator,
	}
}

func (h *helicopter) ApproachAirport(wg *sync.WaitGroup) {
	time.Sleep(1 * time.Second)
	h.airportMediator.CanLandAirport(h)
	fmt.Printf("直升机%s成功垂直降落机场;\n", h.name)
	wg.Done()
}

func (h *helicopter) DepartAirport(wg *sync.WaitGroup) {
	time.Sleep(1 * time.Second)
	fmt.Printf("直升机%s成功垂直起飞,离开机场;\n", h.name)
	h.airportMediator.NotifyWaitingAircraft() // 通知其他等待降落的飞机
	wg.Done()
}


airport_mediator.go

package mediator

// AirportMediator 机场调度中介者
type AirportMediator interface {
	CanLandAirport(aircraft Aircraft) // 排队飞行
	NotifyWaitingAircraft() bool      // 通知等待降落的其他飞机
}

// ApproachTower 机场塔台
type ApproachTower struct {
	waitingQueue chan Aircraft
}

func (a *ApproachTower) CanLandAirport(aircraft Aircraft) {
	a.waitingQueue <- aircraft
}

func (a *ApproachTower) NotifyWaitingAircraft() bool {
	_, ok := <-a.waitingQueue
	if ok {
		return ok
	}
	return false
}

mediator_test.go

package mediator

import (
	"fmt"
	"sync"
	"testing"
	"time"
)

func TestMediator(t *testing.T) {
	// 创建机场调度塔台
	airportMediator := &ApproachTower{make(chan Aircraft)}
	wg := &sync.WaitGroup{}
	// 创建C919客机
	c919Airliner := NewAirliner("C919", airportMediator)
	// 创建米-26重型运输直升机
	m26Helicopter := NewHelicopter("米-26", airportMediator)

	wg.Add(4)
	go c919Airliner.ApproachAirport(wg)  // c919进港降落
	go m26Helicopter.ApproachAirport(wg) // 米-26进港等待

	time.Sleep(1 * time.Second)
	go m26Helicopter.DepartAirport(wg) // 最后米-26飞离
	go c919Airliner.DepartAirport(wg)  // c919飞离,等待的米-26进港降落

	wg.Wait()
	fmt.Println("end -----------")
}

运行结果
=== RUN TestMediator
客机C919成功滑翔起飞,离开机场;
客机C919成功滑翔降落机场;
直升机米-26成功垂直起飞,离开机场;
直升机米-26成功垂直降落机场;
end -----------
— PASS: TestMediator (2.00s)
PASS
ok mediator 2.107s

2.slice 版本

airline.go

package mediator

import "fmt"

// Aircraft 飞机接口
type Aircraft interface {
	ApproachAirport() // 抵达机场空域
	DepartAirport()   // 飞离机场
}

// airliner 客机
type airliner struct {
	name            string          // 客机型号
	airportMediator AirportMediator // 机场调度
}

// NewAirliner 根据指定型号及机场调度创建客机
func NewAirliner(name string, mediator AirportMediator) *airliner {
	return &airliner{
		name:            name,
		airportMediator: mediator,
	}
}

func (a *airliner) ApproachAirport() {
	if !a.airportMediator.CanLandAirport(a) { // 请求塔台是否可以降落
		fmt.Printf("机场繁忙,客机%s继续等待降落;\n", a.name)
		return
	}
	fmt.Printf("客机%s成功滑翔降落机场;\n", a.name)
}

func (a *airliner) DepartAirport() {
	fmt.Printf("客机%s成功滑翔起飞,离开机场;\n", a.name)
	a.airportMediator.NotifyWaitingAircraft() // 通知等待的其他飞机
}

// helicopter 直升机
type helicopter struct {
	name            string
	airportMediator AirportMediator
}

// NewHelicopter 根据指定型号及机场调度创建直升机
func NewHelicopter(name string, mediator AirportMediator) *helicopter {
	return &helicopter{
		name:            name,
		airportMediator: mediator,
	}
}

func (h *helicopter) ApproachAirport() {
	if !h.airportMediator.CanLandAirport(h) { // 请求塔台是否可以降落
		fmt.Printf("机场繁忙,直升机%s继续等待降落;\n", h.name)
		return
	}
	fmt.Printf("直升机%s成功垂直降落机场;\n", h.name)
}

func (h *helicopter) DepartAirport() {
	fmt.Printf("直升机%s成功垂直起飞,离开机场;\n", h.name)
	h.airportMediator.NotifyWaitingAircraft() // 通知其他等待降落的飞机
}

airport_mediator.go

package mediator

// AirportMediator 机场调度中介者
type AirportMediator interface {
	CanLandAirport(aircraft Aircraft) bool // 确认是否可以降落
	NotifyWaitingAircraft()                // 通知等待降落的其他飞机
}

// ApproachTower 机场塔台
type ApproachTower struct {
	hasFreeAirstrip bool
	waitingQueue    []Aircraft // 等待降落的飞机队列
}

func (a *ApproachTower) CanLandAirport(aircraft Aircraft) bool {
	if a.hasFreeAirstrip {
		a.hasFreeAirstrip = false
		return true
	}
	// 没有空余的跑道,加入等待队列
	a.waitingQueue = append(a.waitingQueue, aircraft)
	return false
}

func (a *ApproachTower) NotifyWaitingAircraft() {
	if !a.hasFreeAirstrip {
		a.hasFreeAirstrip = true
	}
	if len(a.waitingQueue) > 0 {
		// 如果存在等待降落的飞机,通知第一个降落
		first := a.waitingQueue[0]
		a.waitingQueue = a.waitingQueue[1:]
		first.ApproachAirport()
	}
}

mediator_test.go

package mediator

import "testing"

func TestMediator(t *testing.T) {
	// 创建机场调度塔台
	airportMediator := &ApproachTower{hasFreeAirstrip: true}
	// 创建C919客机
	c919Airliner := NewAirliner("C919", airportMediator)
	// 创建米-26重型运输直升机
	m26Helicopter := NewHelicopter("米-26", airportMediator)

	c919Airliner.ApproachAirport()  // c919进港降落
	m26Helicopter.ApproachAirport() // 米-26进港等待

	c919Airliner.DepartAirport()  // c919飞离,等待的米-26进港降落
	m26Helicopter.DepartAirport() // 最后米-26飞离
}

运行结果
=== RUN TestMediator
客机C919成功滑翔降落机场;
机场繁忙,直升机米-26继续等待降落;
客机C919成功滑翔起飞,离开机场;
直升机米-26成功垂直降落机场;
直升机米-26成功垂直起飞,离开机场;
— PASS: TestMediator (0.00s)
PASS


总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值