Bridge (Structural)
Intent / problem it solves
Decouple abstraction (what clients use) from implementation (how it works) so they can vary independently. Avoids an explosion of subclasses for every combination.
When to use / when NOT
Use when both dimensions (e.g. UI vs OS, renderer vs shape) change often and inheritance would multiply classes.
Avoid when a single implementation exists or when Strategy already covers the variation cleanly with less structure.
Structure
Abstraction holds a reference to implementor; refined abstractions call through it.
Go example
package main
import "fmt"
type Drawer interface {
Fill(text string) string
}
type AsciiDrawer struct{}
func (AsciiDrawer) Fill(text string) string { return "[" + text + "]" }
type Banner struct {
drawer Drawer
}
func (banner Banner) Show(title string) string {
return banner.drawer.Fill(title)
}
func main() {
banner := Banner{drawer: AsciiDrawer{}}
fmt.Println(banner.Show("sale"))
}JavaScript example
class RemoteRenderer {
paint(shapeName) {
throw new Error('override');
}
}
class SvgRenderer extends RemoteRenderer {
paint(shapeName) {
return `<shape name="${shapeName}" />`;
}
}
class CanvasRenderer extends RemoteRenderer {
paint(shapeName) {
return { engine: 'canvas', shapeName };
}
}
class ShapeAbstraction {
constructor(name, renderer) {
this.name = name;
this.renderer = renderer;
}
draw() {
return this.renderer.paint(this.name);
}
}
const picture = new ShapeAbstraction('triangle', new SvgRenderer());
console.log(picture.draw());Interview phrase
“Bridge separates the thing users interact with from the engine underneath so I can add a new renderer without subclassing every shape.”
Related LLD case studies
Document alongside LLD for multi-backend features (file storage, notifications) in LLD case studies.
Last updated on
Spotted something unclear or wrong on this page?