把「抽象」與「實作」拆成兩條可獨立變化的維度,用組合把它們橋接起來,避免兩維度相乘造成的子類別爆炸。
🧠 When to Use
TIP
訊號:你的類別有兩個獨立變動的維度(如 形狀 × 繪圖 API),用繼承會變成 形狀數 × API 數 個子類別。
- 抽象與實作都會各自演化,想各自獨立擴充。
- 想避免「N 種抽象 × M 種實作」的繼承爆炸。
- 想在執行期切換實作(而非編譯期綁死)。
⚖️ Structure & Variants
經典版 — 形狀 × 繪圖 API
// 實作維度(Implementor)
interface Renderer { fun drawCircle(r: Float) }
class VectorRenderer : Renderer { override fun drawCircle(r: Float) { /* svg */ } }
class RasterRenderer : Renderer { override fun drawCircle(r: Float) { /* pixels */ } }
// 抽象維度,持有一個 Renderer(這就是「橋」)
abstract class Shape(protected val renderer: Renderer) { abstract fun draw() }
class Circle(renderer: Renderer, val r: Float) : Shape(renderer) {
override fun draw() = renderer.drawCircle(r)
}
val c = Circle(VectorRenderer(), 5f) // 兩維度自由組合- 抽象端(Shape)與實作端(Renderer)各自繼承,靠組合連接,不相乘。
和 Adapter 的差別
- Bridge:設計前期就刻意把兩維度拆開,讓它們平行演化。
- Adapter:事後把既有不相容介面接起來,常是補救既有程式。
- 結構相似(都靠組合),差在意圖與時機。
和 Abstract Factory 的搭配
- Bridge 決定「抽象怎麼接到實作」;Abstract Factory 可負責生產正確的 implementor 家族。
- 兩者常搭配:Factory 建好實作物件,注入給 Bridge 的抽象端。
⚠️ Misuse & Anti-patterns
- 只有一個維度會變還硬拆:抽象與實作沒有各自獨立演化時,Bridge 只是徒增間接層。
- 抽象端洩漏實作細節:抽象不該假設特定 implementor,否則兩維度又黏回去。
- 把 Bridge 當 Adapter 用:事後補救既有介面是 Adapter,不是事前的維度拆分。
🔑 Takeaways
- 解決的是「兩維度相乘的繼承爆炸」:把抽象與實作拆成兩條獨立的繼承線。
- 核心手法是組合優於繼承——抽象端持有實作端。
- 和 Adapter 結構像,差在 Bridge 是事前刻意設計、兩維度平行演化。
No notes yet — jot your takeaways or Q&A here.