桥接模式通过接口与组合分离抽象与实现,使二者独立变化。Go 中以接口定义实现行为(如 LoggerImpl),具体类型实现细节(ConsoleLogger、FileLogger),抽象层(Logger)持有接口实例,依赖接口而非具体类型,实现解耦。新增输出方式无需修改日志逻辑,支持扩展与复用,运行时可切换实现,如 NewLogger(&ConsoleLogger{})与 NewLogger(&FileLogger{})分别输出到控制台和文件,调用一致但行为不同。区别于策略模式,桥接侧重多维度独立变化的结构设计,而非算法替换。

桥接模式的核心是将抽象与实现分离,让两者可以独立变化。在 Golang 中,虽然没有继承机制,但通过接口和组合,能更自然地实现桥接模式,有效解耦模块。
理解桥接模式的关键结构
桥接模式包含两个核心部分:抽象部分和实现部分。它们通过组合连接,而不是继承。
在 Golang 中,通常用接口表示“实现”层,由具体类型实现;而“抽象”层则持有该接口的实例,通过调用接口方法来完成任务。
重点: 不要让高层模块依赖具体实现,而是依赖于接口。
实际例子:日志系统解耦
设想一个日志模块,支持多种输出方式(控制台、文件、网络),同时支持不同日志级别处理逻辑。如果直接耦合,每新增一种输出方式就要修改多个地方。
使用桥接模式,我们可以这样设计:
定义实现接口(输出行为):
type LoggerImpl interface {Write(message string) }
具体实现:
type ConsoleLogger struct{} func (c *ConsoleLogger) Write(message string) {fmt.Println("Console:", message) } type FileLogger struct{} func (f *FileLogger) Write(message string) {// 模拟写入文件 fmt.Println("File:", message) }
抽象层(日志级别处理):
type Logger struct {impl LoggerImpl} func NewLogger(impl LoggerImpl) *Logger {return &Logger{impl: impl} } func (l *Logger) Info(msg string) {l.impl.Write("[INFO] " + msg) } func (l *Logger) Error(msg string) {l.impl.Write("[ERROR] " + msg) }
这样,抽象的 Logger 结构体不关心写入哪里,只依赖 LoggerImpl 接口。新增输出方式时,无需改动日志级别逻辑。
桥接带来的解耦优势
- 扩展实现更简单:增加新的
LoggerImpl实现,比如NetworkLogger,不需要动抽象层代码 - 抽象可复用:同一个实现可以被不同的抽象使用,比如调试日志和审计日志共用文件写入逻辑
- 运行时切换实现:可以在初始化时传入不同实现,灵活配置
例如:
consoleLog := NewLogger(&ConsoleLogger{}) fileLog := NewLogger(&FileLogger{}) consoleLog.Info(" 程序启动 ") fileLog.Error(" 文件未找到 ")
两者的调用方式一致,但背后行为完全不同。
避免常见误区
有些人会把桥接和策略模式混淆。区别 在于:桥接关注的是“抽象和实现两个维度的变化”,而策略更侧重算法替换。桥接通常是结构性的长期设计,策略常用于运行时动态选择行为。
在 Golang 中,不要试图模拟类继承体系,利用接口最小化和组合,反而能让桥接模式更简洁清晰。
基本上就这些。桥接模式在 Go 里用得自然,关键是分清哪些是抽象职责,哪些是实现细节,然后用接口隔离它们。不复杂但容易忽略。






























