当前位置: 首页 > news >正文

Go语言设计模式:桥接模式详解

文章目录

    • 一、桥接模式概述
      • 1. 什么是桥接模式?
      • 1.2 现实生活中的比喻
      • 1.3 桥接模式优缺点
      • 1.4 适用场景
      • 1.5 桥接模式的UML图与核心角色
    • 二、Go语言实现:经典的遥控器例子
      • 第1步:定义实现者接口和具体实现
      • 第2步:定义抽象和精炼抽象
      • 第3步:客户端使用
      • 完整代码
    • 三、Go语言实现:跨平台消息推送例子
      • 第1步:定义实现者接口和具体实现
      • 第2步:定义抽象和精炼抽象
      • 第3步:客户端使用
      • 完整代码

一、桥接模式概述

1. 什么是桥接模式?

桥接模式旨在解决当一个类存在多个维度的变化时,如何避免类数量爆炸式增长的问题。它通过使用组合而不是继承,将两个变化维度解耦。

1.2 现实生活中的比喻

  • 遥控器与电器:这是一个最经典的比喻。
    • 抽象部分:遥控器。不同品牌的遥控器(如索尼、三星)可能有不同的外形和按钮布局(这是一个变化维度)。
    • 实现部分:电器。遥控器可以控制电视、空调、音响等(这是另一个变化维度)。
    • 桥接:遥控器内部有一个“桥”(红外线发射器),它将用户的按键操作(抽象)转换成电器能理解的指令(实现)。你可以用同一个索尼遥控器(抽象)去控制不同型号的索尼电视(实现),也可以用三星遥控器(抽象)去控制三星电视(实现)。遥控器和电器的设计可以独立升级,互不影响。

1.3 桥接模式优缺点

优点:

  • 解耦抽象和实现:这是最大的优点。它允许你独立地修改抽象部分和实现部分,而不会相互影响。
  • 优秀的扩展能力:你可以轻松地增加新的抽象或新的实现,而无需修改现有代码,符合开闭原则。
  • 遵守单一职责原则:将复杂的类拆分成两个独立的类结构,每个类只负责一个维度的变化。
  • 对客户端隐藏实现细节:客户端只与抽象部分交互,无需关心具体的实现。

缺点:

  • 增加系统复杂性:引入了额外的抽象层,对于简单的场景可能会过度设计,增加理解难度。
  • 需要正确识别两个维度:在设计初期,需要准确地识别出系统中哪些是变化的抽象维度,哪些是变化的实现维度,这对设计者的经验有一定要求。

1.4 适用场景

  • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。这是最典型的场景。
  • 不希望使用继承或因为多层继承导致系统类数量急剧增加
  • 希望在运行时动态切换不同的实现

1.5 桥接模式的UML图与核心角色

桥接模式包含以下四个核心角色:

  • Abstraction(抽象):定义抽象接口,并持有一个对 Implementor 的引用。
  • RefinedAbstraction(精炼抽象):扩展 Abstraction 的接口,通常是业务逻辑的具体实现。
  • Implementor(实现者接口):定义实现部分的接口,这个接口不一定要与 Abstraction 的接口完全一致,事实上它们通常是不一样的。
  • ConcreteImplementor(具体实现者):实现 Implementor 接口,是具体的实现逻辑。
    UML 类图:
+----------------+       +---------------------+
|   Client       |------>|    Abstraction      |
+----------------+       +---------------------+| - implementor: Implementor |+---------------------+| + Operation()       |+---------------------+^| extends|
+---------------------+       +---------------------+
| RefinedAbstraction  |------>|    Implementor      |
+---------------------+       +---------------------+
| + Operation()       |       | + OperationImpl()   |
+---------------------+       +---------------------+^| implements|+---------------------+| ConcreteImplementorA|+---------------------+| + OperationImpl()   |+---------------------+

二、Go语言实现:经典的遥控器例子

我们用遥控器和电器的例子来模拟桥接模式。

第1步:定义实现者接口和具体实现

// Implementor: 实现者接口,定义电器的操作
type Device interface {TurnOn()TurnOff()SetVolume(volume int)
}
// ConcreteImplementorA: 具体实现者 - 电视
type TV struct {volume int
}
func (tv *TV) TurnOn() {fmt.Println("TV is turned ON")
}
func (tv *TV) TurnOff() {fmt.Println("TV is turned OFF")
}
func (tv *TV) SetVolume(volume int) {tv.volume = volumefmt.Printf("TV volume is set to %d\n", tv.volume)
}
// ConcreteImplementorB: 具体实现者 - 收音机
type Radio struct {volume int
}
func (r *Radio) TurnOn() {fmt.Println("Radio is turned ON")
}
func (r *Radio) TurnOff() {fmt.Println("Radio is turned OFF")
}
func (r *Radio) SetVolume(volume int) {r.volume = volumefmt.Printf("Radio volume is set to %d\n", r.volume)
}

第2步:定义抽象和精炼抽象

// Abstraction: 抽象部分 - 遥控器
type RemoteControl struct {device Device // 持有实现者的引用
}
// NewRemoteControl 是构造函数
func NewRemoteControl(device Device) *RemoteControl {return &RemoteControl{device: device}
}
// 基础功能,委托给实现者
func (rc *RemoteControl) TurnOn() {rc.device.TurnOn()
}
func (rc *RemoteControl) TurnOff() {rc.device.TurnOff()
}
// RefinedAbstraction: 精炼抽象 - 高级遥控器
type AdvancedRemoteControl struct {*RemoteControl // 通过组合(嵌入)扩展基础遥控器
}
func NewAdvancedRemoteControl(device Device) *AdvancedRemoteControl {return &AdvancedRemoteControl{RemoteControl: NewRemoteControl(device)}
}
// 扩展的新功能
func (arc *AdvancedRemoteControl) Mute() {fmt.Println("Remote: Muting the device")arc.device.SetVolume(0)
}

第3步:客户端使用

func main() {fmt.Println("--- Testing with TV ---")tv := &TV{}tvRemote := NewAdvancedRemoteControl(tv)tvRemote.TurnOn()tvRemote.device.SetVolume(10) // 直接访问实现者tvRemote.Mute()tvRemote.TurnOff()fmt.Println("\n--- Testing with Radio ---")radio := &Radio{}radioRemote := NewAdvancedRemoteControl(radio)radioRemote.TurnOn()radioRemote.device.SetVolume(5)radioRemote.Mute()radioRemote.TurnOff()
}

完整代码

文件:bridge_remote.go

package main
import "fmt"
// ======================
// 1. 定义实现者接口和具体实现
// ======================
// Implementor: 实现者接口,定义电器的操作
type Device interface {TurnOn()TurnOff()SetVolume(volume int)
}
// ConcreteImplementorA: 具体实现者 - 电视
type TV struct {volume int
}
func (tv *TV) TurnOn() {fmt.Println("TV is turned ON")
}
func (tv *TV) TurnOff() {fmt.Println("TV is turned OFF")
}
func (tv *TV) SetVolume(volume int) {tv.volume = volumefmt.Printf("TV volume is set to %d\n", tv.volume)
}
// ConcreteImplementorB: 具体实现者 - 收音机
type Radio struct {volume int
}
func (r *Radio) TurnOn() {fmt.Println("Radio is turned ON")
}
func (r *Radio) TurnOff() {fmt.Println("Radio is turned OFF")
}
func (r *Radio) SetVolume(volume int) {r.volume = volumefmt.Printf("Radio volume is set to %d\n", r.volume)
}
// ======================
// 2. 定义抽象和精炼抽象
// ======================
// Abstraction: 抽象部分 - 遥控器
type RemoteControl struct {device Device // 持有实现者的引用
}
// NewRemoteControl 是构造函数
func NewRemoteControl(device Device) *RemoteControl {return &RemoteControl{device: device}
}
// 基础功能,委托给实现者
func (rc *RemoteControl) TurnOn() {rc.device.TurnOn()
}
func (rc *RemoteControl) TurnOff() {rc.device.TurnOff()
}
// RefinedAbstraction: 精炼抽象 - 高级遥控器
type AdvancedRemoteControl struct {*RemoteControl // 通过组合(嵌入)扩展基础遥控器
}
func NewAdvancedRemoteControl(device Device) *AdvancedRemoteControl {return &AdvancedRemoteControl{RemoteControl: NewRemoteControl(device)}
}
// 扩展的新功能
func (arc *AdvancedRemoteControl) Mute() {fmt.Println("Remote: Muting the device")arc.device.SetVolume(0)
}
// ======================
// 3. 客户端使用
// ======================
func main() {fmt.Println("--- Testing with TV ---")tv := &TV{}tvRemote := NewAdvancedRemoteControl(tv)tvRemote.TurnOn()tvRemote.device.SetVolume(10) // 直接访问实现者tvRemote.Mute()tvRemote.TurnOff()fmt.Println("\n--- Testing with Radio ---")radio := &Radio{}radioRemote := NewAdvancedRemoteControl(radio)radioRemote.TurnOn()radioRemote.device.SetVolume(5)radioRemote.Mute()radioRemote.TurnOff()
}

执行结果:

--- Testing with TV ---
TV is turned ON
TV volume is set to 10
Remote: Muting the device
TV volume is set to 0
TV is turned OFF
--- Testing with Radio ---
Radio is turned ON
Radio volume is set to 5
Remote: Muting the device
Radio volume is set to 0
Radio is turned OFF

在这个例子中,AdvancedRemoteControl(抽象)和 TV/Radio(实现)完全解耦。你可以轻松地增加新的电器(如音响)或新的遥控器(如语音遥控器),而无需修改对方。

三、Go语言实现:跨平台消息推送例子

这是一个更贴近实际开发的例子。假设我们需要一个消息推送系统,它可以发送不同类型的消息(紧急、普通),并且需要支持不同的推送渠道(邮件、短信)。

  • 变化维度1(抽象):消息类型(普通消息、紧急消息)。
  • 变化维度2(实现):推送渠道(邮件、短信)。

第1步:定义实现者接口和具体实现

// Implementor: 消息推送渠道接口
type MessageSender interface {Send(message, recipient string)
}
// ConcreteImplementorA: 邮件推送
type EmailSender struct{}
func (es *EmailSender) Send(message, recipient string) {fmt.Printf("Sending Email to %s: '%s'\n", recipient, message)
}
// ConcreteImplementorB: 短信推送
type SMSSender struct{}
func (ss *SMSSender) Send(message, recipient string) {fmt.Printf("Sending SMS to %s: '%s'\n", recipient, message)
}

第2步:定义抽象和精炼抽象

// Abstraction: 消息抽象
type Message struct {sender MessageSendercontent stringrecipient string
}
func NewMessage(sender MessageSender, content, recipient string) *Message {return &Message{sender: sender,content: content,recipient: recipient,}
}
func (m *Message) Send() {m.sender.Send(m.content, m.recipient)
}
// RefinedAbstraction: 紧急消息
type UrgentMessage struct {*Message
}
func NewUrgentMessage(sender MessageSender, content, recipient string) *UrgentMessage {return &UrgentMessage{Message: NewMessage(sender, content, recipient),}
}
// 重写或扩展发送行为
func (um *UrgentMessage) Send() {// 添加紧急消息的前缀urgentContent := "[URGENT] " + um.contentfmt.Println("Processing urgent message with high priority...")um.sender.Send(urgentContent, um.recipient)
}

第3步:客户端使用

func main() {fmt.Println("--- Scenario 1: Normal message via Email ---")emailSender := &EmailSender{}normalEmailMsg := NewMessage(emailSender, "This is a normal email.", "user@example.com")normalEmailMsg.Send()fmt.Println("\n--- Scenario 2: Urgent message via SMS ---")smsSender := &SMSSender{}urgentSMSMsg := NewUrgentMessage(smsSender, "Server is down!", "admin-phone")urgentSMSMsg.Send()fmt.Println("\n--- Scenario 3: Urgent message via Email (reusing implementation) ---")urgentEmailMsg := NewUrgentMessage(emailSender, "Critical security update!", "security-team@example.com")urgentEmailMsg.Send()
}

完整代码

文件:bridge_message.go

package main
import "fmt"
// ======================
// 1. 定义实现者接口和具体实现
// ======================
// Implementor: 消息推送渠道接口
type MessageSender interface {Send(message, recipient string)
}
// ConcreteImplementorA: 邮件推送
type EmailSender struct{}
func (es *EmailSender) Send(message, recipient string) {fmt.Printf("Sending Email to %s: '%s'\n", recipient, message)
}
// ConcreteImplementorB: 短信推送
type SMSSender struct{}
func (ss *SMSSender) Send(message, recipient string) {fmt.Printf("Sending SMS to %s: '%s'\n", recipient, message)
}
// ======================
// 2. 定义抽象和精炼抽象
// ======================
// Abstraction: 消息抽象
type Message struct {sender    MessageSendercontent   stringrecipient string
}
func NewMessage(sender MessageSender, content, recipient string) *Message {return &Message{sender:    sender,content:   content,recipient: recipient,}
}
func (m *Message) Send() {m.sender.Send(m.content, m.recipient)
}
// RefinedAbstraction: 紧急消息
type UrgentMessage struct {*Message
}
func NewUrgentMessage(sender MessageSender, content, recipient string) *UrgentMessage {return &UrgentMessage{Message: NewMessage(sender, content, recipient),}
}
// 重写或扩展发送行为
func (um *UrgentMessage) Send() {// 添加紧急消息的前缀urgentContent := "[URGENT] " + um.contentfmt.Println("Processing urgent message with high priority...")um.sender.Send(urgentContent, um.recipient)
}
// ======================
// 3. 客户端使用
// ======================
func main() {fmt.Println("--- Scenario 1: Normal message via Email ---")emailSender := &EmailSender{}normalEmailMsg := NewMessage(emailSender, "This is a normal email.", "user@example.com")normalEmailMsg.Send()fmt.Println("\n--- Scenario 2: Urgent message via SMS ---")smsSender := &SMSSender{}urgentSMSMsg := NewUrgentMessage(smsSender, "Server is down!", "admin-phone")urgentSMSMsg.Send()fmt.Println("\n--- Scenario 3: Urgent message via Email (reusing implementation) ---")urgentEmailMsg := NewUrgentMessage(emailSender, "Critical security update!", "security-team@example.com")urgentEmailMsg.Send()
}

执行结果:

--- Scenario 1: Normal message via Email ---
Sending Email to user@example.com: 'This is a normal email.'
--- Scenario 2: Urgent message via SMS ---
Processing urgent message with high priority...
Sending SMS to admin-phone: '[URGENT] Server is down!'
--- Scenario 3: Urgent message via Email (reusing implementation) ---
Processing urgent message with high priority...
Sending Email to security-team@example.com: '[URGENT] Critical security update!'

这个例子完美地展示了桥接模式的威力:消息类型和推送渠道可以自由组合,并且可以独立扩展。新增一个“App推送”渠道或“普通消息”类型,都无需改动现有代码。

总结:桥接模式是一个强大的工具,用于管理系统中多个维度的变化。

  • 核心是“组合”:在Go中,通过结构体嵌入(*RemoteControl)或直接持有接口(sender MessageSender)来实现组合,这是桥接模式的关键。
  • 识别维度是关键:在设计时,要问自己:“这个系统中有哪些东西是独立变化的?” 找到这些维度,就可以用桥接模式将它们分离。
  • 区别于策略模式:桥接模式和策略模式在结构上有些相似(都使用组合),但意图不同
    • 策略模式的目的是封装算法,让它们可以互相替换,通常只有一个变化维度(算法)。
    • 桥接模式的目的是分离抽象和实现,使两者可以独立变化,通常有两个或更多的变化维度。
http://www.dtcms.com/a/549774.html

相关文章:

  • 前端(Vue3)如何接收后端(SpringBoot)返回的文件并下载
  • 低空经济网络安全体系
  • 福建省建设资格注册中心网站东莞网站推广技巧
  • 汉阳做网站多少钱网站服务器时间查询工具
  • WPF的MVVM模式核心架构与实现细节
  • HarmonyOS 开发高级认证是什么?含金量高吗?
  • 做国外的众筹网站怎么办一个网站
  • 网站设计联盟兰州关键词优化排名
  • 【AI WorkFow】n8n 源码分析-工作流引擎实现原理(五)
  • 技术分享 | torch.profiler:利用探针收集模型执行信息的性能分析工具
  • zynq7000- linux平台 PS读写PL测试
  • 【JavaScript性能优化实战】
  • React Hook为什么这么“严格“?链表内部机制大揭秘
  • 爬虫进阶 JS逆向基础超详细,解锁加密数据
  • GF框架直接使用SQL语句查询数据库的指南
  • 美食网站素材怎么在网上卖产品
  • 网站建设综合实训设计报告怎么做单位网站
  • JavaWeb后端-JDBC、MyBatis
  • 网站访问流程改变WordPress界面
  • 聚合API平台如何重构AI开发效率?
  • 设计模式之单例模式:一个类就只有一个实例
  • 分布式数据库选型指南 (深入对比TiDB与OceanBase)
  • 模板方法模式:优雅地封装算法骨架
  • 有哪些做ppt用图片的网站有哪些免费咨询皮肤科医生在线
  • 理解 MySQL 架构:从连接到存储的全景视图
  • 电商网站 服务器易派客网站是谁做的
  • 大型语言模型(LLM)架构大比拼
  • 爱派(AiPy):一个让大语言模型直接操作Python完成任务
  • 【一加手机Bootloader解锁政策更新通知】
  • 什么是政企工作手机,有什么功能作用