桥接模式在Go中通过接口定义行为契约、结构体字段组合实现解耦,而非传统继承;Shape与Renderer接口互不依赖,Circle等类型持Renderer实例委托绘制,确保运行时可任意替换渲染器实现。

桥接模式在 Go 里根本不用“实现”,而是靠接口和组合自然达成
Go 没有类继承,也不支持抽象类或“桥接抽象与实现”的传统 UML 建模方式。所谓“Golang 实现桥接模式”,其实是用 interface 定义行为契约,用结构体字段持有具体实现(即组合),让抽象部分(如 Renderer)和实现部分(如 WindowsRenderer、LinuxRenderer)解耦。这不是模拟设计模式,而是 Go 的惯用法。
定义清晰的接口:抽象层和实现层各一个 interface
关键不是写多少结构体,而是把职责切开。比如图形渲染场景:
-
Shape接口只声明Draw(),不关心怎么画 -
Renderer接口只声明RenderLine()、RenderPoint()等底层能力,不关心画什么 - 两者之间**不互相依赖**,
Shape内部持有一个Renderer实例来委托绘制
错误做法是让 Shape 直接调用 WindowsRenderer.DrawLine() —— 这就又紧耦合了。
结构体组合实现桥接:用字段而非嵌入
组合时明确使用字段名(如 r Renderer),而不是匿名嵌入(Renderer)。后者容易模糊边界,导致误调用实现细节。
立即学习“go语言免费学习笔记(深入)”;
type Circle struct {
x, y, r float64
r Renderer // 显式命名,强调“我用你,但我不属于你”
}
func (c *Circle) Draw() {
c.r.RenderCircle(c.x, c.y, c.r) // 委托给 renderer,不暴露 renderer 类型
}
注意:Circle 不需要知道 c.r 是 *OpenGLRenderer 还是 *SVGRenderer,只要它满足 Renderer 接口即可。
避免常见陷阱:别在接口里塞实现细节
容易踩的坑包括:
- 把平台相关类型(如
syscall.Handle、*C.GdkWindow)放进Renderer接口方法签名里 —— 这会让接口无法跨平台实现 - 让
Shape实现Renderer接口(即“自己画自己”)—— 违反桥接初衷,失去替换渲染器的能力 - 用
func类型代替interface来做“桥接”—— 虽然能跑,但丧失类型安全和可扩展性(比如没法加新方法) - 在
NewCircle(r Renderer)构造函数里对r做类型断言(if w, ok := r.(*WindowsRenderer))—— 直接破坏桥接效果
桥接是否生效,就看能不能在运行时任意替换 Renderer 实现而不改 Shape 代码。做不到这点,就只是写了两个无关结构体而已。










