Bridge tách abstraction khỏi implementation để cả hai có thể thay đổi độc lập — giải quyết 'Cartesian product' explosion khi có nhiều dimension.
Ví dụ: Shape (Circle, Square) × Renderer (SVGRenderer, CanvasRenderer) = 4 class nếu dùng inheritance, nhưng với Bridge chỉ cần 2+2 class:
class Circle {
constructor(private renderer: Renderer, private radius: number) {}
draw() {
this.renderer.renderCircle(this.radius)
}
}
class Square {
constructor(private renderer: Renderer, private side: number) {}
draw() {
this.renderer.renderSquare(this.side)
}
}- Khác Adapter: Adapter giải quyết incompatibility giữa existing interfaces (fix sau); Bridge thiết kế từ đầu để tách abstraction-implementation (design upfront).
- Dùng Bridge khi: muốn tránh class explosion do kết hợp nhiều dimension; khi abstraction và implementation cần thay đổi độc lập; khi muốn share implementation giữa nhiều object.
- Không dùng khi: chỉ có một dimension biến đổi — over-engineering.
Bridge decouples abstraction from implementation so that the two can vary independently — solving the class explosion that occurs when combining multiple dimensions.
Example: Shape (Circle, Square) × Renderer (SVGRenderer, CanvasRenderer) = 4 classes with inheritance, but Bridge only requires 2 + 2 classes:
class Circle {
constructor(private renderer: Renderer, private radius: number) {}
draw() {
this.renderer.renderCircle(this.radius)
}
}
class Square {
constructor(private renderer: Renderer, private side: number) {}
draw() {
this.renderer.renderSquare(this.side)
}
}Difference from Adapter: Adapter resolves incompatibility between existing interfaces (a retrofit fix); Bridge is designed upfront to separate abstraction from implementation.
- Use Bridge when you want to avoid class explosion from combining multiple dimensions, when abstraction and implementation need to evolve independently, or when you want to share an implementation across multiple objects.
- Avoid it when only one dimension varies — that's over-engineering.