【设计模式】6、bridge 桥接模式

六、bridge 桥接模式

桥接设计模式

  1. 复杂逻辑拆分:

如果需要完成复杂的逻辑,可以把复杂逻辑设计为接口,内部再拆分为若干接口。这样复杂的逻辑会被拆分开,方便解耦。

例如:如果遥控器控制设备。可以遥控器设计为复杂接口,设备设计为简单接口。遥控器的每个方法都由若干设备接口组成。设备可以有多种实现:如电视、手机等。

  1. 多维,避免组合爆炸

如果有多个维度,各维度之间可以设计为接口,而不是让组合的数量爆炸。

例如:如果有 mac 和 windows 两种 os,需要分别连接 hp 和 epson 的打印机打印。为了避免实现 2x2 种组合类型(如 mac-hp、mac-epson、windows-hp、windows-epson 等),可以用接口。

6.1 多维:os 和 printer

Go 桥接模式讲解和代码示例

目录层级如下:

06bridge/061osprinter
├── epson_printer.go
├── hp_printer.go
├── mac_os.go
├── os.go
├── os_test.go
├── printer.go
├── readme.md
└── windows_os.go

6.1.1 os.go

package _61osprinter

type os interface {
	Print()
	SetPrinter(p printer)
}

6.1.2 os_test.go

package _61osprinter

import (
	"fmt"
	"testing"
)

/*
=== RUN   TestOsPrint
mac系统
hp打印机

mac系统
爱普生打印机

windows系统
hp打印机

windows系统
爱普生打印机

--- PASS: TestOsPrint (0.00s)
PASS
*/
func TestOsPrint(t *testing.T) {
	hp := &hpPrinter{}
	epson := &epsonPrinter{}

	// mac
	mac := &macOs{}
	mac.SetPrinter(hp)
	mac.Print()
	fmt.Println()

	mac.SetPrinter(epson)
	mac.Print()
	fmt.Println()

	// win
	win := &windowsOs{}
	win.SetPrinter(hp)
	win.Print()
	fmt.Println()

	win.SetPrinter(epson)
	win.Print()
	fmt.Println()
}

6.1.3 os.go

package _61osprinter

type os interface {
	Print()
	SetPrinter(p printer)
}

6.1.4 priner.go

package _61osprinter

type printer interface {
	Print()
}

6.1.5 mac_os.go

package _61osprinter

import "fmt"

type macOs struct {
	printer printer
}

func (o *macOs) Print() {
	fmt.Println("mac系统")
	o.printer.Print()
}

func (o *macOs) SetPrinter(p printer) {
	o.printer = p
}

6.1.6 windows_os.go

package _61osprinter

import "fmt"

type windowsOs struct {
	printer printer
}

func (o *windowsOs) Print() {
	fmt.Println("windows系统")
	o.printer.Print()
}

func (o *windowsOs) SetPrinter(p printer) {
	o.printer = p
}

6.1.7 hp_printer.go

package _61osprinter

import "fmt"

type hpPrinter struct {
}

func (p *hpPrinter) Print() {
	fmt.Println("hp打印机")
}

6.1.8 epson_printer.go

package _61osprinter

import "fmt"

type epsonPrinter struct{}

func (p *epsonPrinter) Print() {
	fmt.Println("爱普生打印机")
}

6.2 client、remote、device

桥接设计模式

如果 client 希望控制 remote,remote 希望控制 device,device 可能有多种。可以将 remote 和 device 都抽象为接口。

06bridge/062client_remote_device
├── bluetooth_remote.go
├── device.go
├── infrared_remote.go
├── radio_device.go
├── readme.md
├── remote.go
├── remote_test.go
└── tv_device.go

6.2.1 remote_test.go

package _62client_remote_device

import "testing"

func TestTvRemote(t *testing.T) {
	rs := []remote{
		&infraredRemote{dev: &tvDevice{}},
		&infraredRemote{dev: &radioDevice{}},
		&bluetoothRemote{dev: &tvDevice{}},
		&bluetoothRemote{dev: &radioDevice{}},
	}
	for _, r := range rs {
		r.togglePower()
		r.channelUp()
	}
}

6.2.2 remote.go

package _62client_remote_device

type remote interface {
	togglePower()
	channelUp()
}

6.2.3 device.go

package _62client_remote_device

type device interface {
	// 开关
	isEnabled() bool
	enable()
	disable()
	// 频道
	getChannel() int
	setChannel(c int)
}

6.2.4 infrared_remote.go

package _62client_remote_device

// 红外遥控器
type infraredRemote struct {
	dev device
}

func (r *infraredRemote) togglePower() {
	if r.dev.isEnabled() {
		r.dev.disable()
	} else {
		r.dev.enable()
	}
}

func (r *infraredRemote) channelUp() {
	old := r.dev.getChannel()
	r.dev.setChannel(old + 1)
}

6.2.5 bluetooth_remote.go

package _62client_remote_device

// 蓝牙遥控器
type bluetoothRemote struct {
	dev device
}

func (r *bluetoothRemote) togglePower() {
	if r.dev.isEnabled() {
		r.dev.disable()
	} else {
		r.dev.enable()
	}
}

func (r *bluetoothRemote) channelUp() {
	old := r.dev.getChannel()
	r.dev.setChannel(old + 1)
}

6.2.6 tv_device.go

package _62client_remote_device

type tvDevice struct {
	// 开关
	enabled bool
	// 频道
	channel int
}

func (d *tvDevice) isEnabled() bool {
	return d.enabled
}

func (d *tvDevice) enable() {
	d.enabled = true
}

func (d *tvDevice) disable() {
	d.enabled = false
}

func (d *tvDevice) getChannel() int {
	return d.channel
}

func (d *tvDevice) setChannel(c int) {
	d.channel = c
}

6.2.7 radio_device.go

package _62client_remote_device

type radioDevice struct {
	enabled bool
	channel int
}

func (d *radioDevice) isEnabled() bool {
	return d.enabled
}

func (d *radioDevice) enable() {
	d.enabled = true
}

func (d *radioDevice) disable() {
	d.enabled = false
}

func (d *radioDevice) getChannel() int {
	return d.channel
}

func (d *radioDevice) setChannel(c int) {
	d.channel = c
}

6.3 notifier_sender

需要实现一个通知发送器, 有如下两个维度:

  1. 生产消息: 根据内容, 生产消息
  2. 触达用户: 利用网络, 发消息给用户

这其实是两个步骤, 可以拆分开, 使解耦.

06bridge/063notifier_sender
├── notifier.go
├── notifier_test.go
├── readme.md
└── sender.go

6.3.1 notifier_test.go

package _63notifier_sender

import "testing"

/*
=== RUN   TestNotify
广告通知
通过微信发送
广告通知
通过飞书发送
广告通知
通过电话发送
欢迎通知
通过微信发送
欢迎通知
通过飞书发送
欢迎通知
通过电话发送
--- PASS: TestNotify (0.00s)
PASS
*/
func TestNotify(t *testing.T) {
	ns := []Notifier{
		&AdvertisementNotifier{sender: &WechatSender{}},
		&AdvertisementNotifier{sender: &LarkSender{}},
		&AdvertisementNotifier{sender: &PhoneSender{}},

		&GreetingNotifier{&WechatSender{}},
		&GreetingNotifier{&LarkSender{}},
		&GreetingNotifier{&PhoneSender{}},
	}
	for _, n := range ns {
		n.Notify()
	}
}

6.3.2 notifier.go

package _63notifier_sender

import "fmt"

// Notifier 通知者
type Notifier interface {
	Notify()
}

type AdvertisementNotifier struct {
	sender Sender
}

func (n *AdvertisementNotifier) Notify() {
	fmt.Println("广告通知")
	n.sender.Send()
}

type GreetingNotifier struct {
	Sender
}

func (n *GreetingNotifier) Notify() {
	fmt.Println("欢迎通知")
	n.Send()
}

6.3.3 sender.go

package _63notifier_sender

import (
	"fmt"
)

type Sender interface {
	Send()
}

type WechatSender struct {
}

func (s *WechatSender) Send() {
	fmt.Println("通过微信发送")
}

type LarkSender struct {
}

func (s *LarkSender) Send() {
	fmt.Println("通过飞书发送")
}

type PhoneSender struct{}

func (s *PhoneSender) Send() {
	fmt.Println("通过电话发送")
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值