structural

Bridge

Decouple abstractions from implementations so they can evolve independently.

Problem

structural

When an abstraction is tightly coupled to its implementation, changing one side forces changes in the other and makes the system harder to evolve.

Integration notes

Bridge is useful when you want one stable abstraction while swapping implementations for providers, environments, or device targets.

Tradeoffs

  • Adds an extra layer of indirection.
  • Can increase the number of moving parts.
  • Makes abstractions and implementations easier to evolve independently.

Languages

typescript, java, python, angular, react, react-native, csharp, dotnet, go

Platforms

web, backend, mobile, integration, ui

Variants

frontend

Device control bridge

typescript

Bridge UI controls to different devices or rendering targets while preserving one control surface.

Intent: Keep the user-facing abstraction stable while device behavior varies behind it.

Problem: UI code becomes hard to evolve when controls are directly wired to specific device implementations.

Solution: Use a bridge so the control layer delegates to a replaceable device implementation.

Dependencies

bridge

Related variants

bridge-backend-providerbridge-integration-contract

Examples

bridge

This fits remotes, dashboards, canvas renderers, and any UI that needs to target multiple implementations.

Scenarios

Remote control bridge

A remote control triggers TVs, speakers, and streaming devices through interchangeable device implementations.

Context: A home automation app needs one control surface that can operate several device brands and categories.

Problem: Tight coupling between controls and specific devices makes the remote hard to extend.

Solution: Use Bridge to separate the remote control abstraction from the device implementation.

frontend

Language examples

Core languages

Frameworks and libraries

Angular remote bridgeangular

Angular services can separate remote commands from the device implementation.

Angular
export interface Device {
  on(): void;
  off(): void;
  setVolume(level: number): void;
}

export class RemoteControl {
  constructor(private device: Device) {}

  powerOn() {
    this.device.on();
  }
}

Real-world examples

  • Cross-database reporting: Reporting systems often need one query abstraction while switching between SQL engines and data providers.
  • Multi-channel messaging: Notification platforms need to keep message composition separate from delivery channels like email, SMS, and push.
  • Payment processor support: E-commerce systems frequently need one checkout flow while swapping payment gateways by region or merchant.