THN Interview Prep

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.

Loading diagram…

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.”

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?

On this page