๐ What is the Bridge Pattern? (Simple Explanation)
Bridge Pattern means:
"Separate abstraction from implementation so they can evolve independently."
โก๏ธ Instead of tying two things together tightly (hard-coded),
you connect them through a โbridgeโ interface.
Think about it like remotely controlling something:
- The remote control (abstraction)
- The TV (implementation)
They work together, but you could swap either one independently.
๐จ Real-World Examples (Easy to Visualize)
๐ฎ 1. Game Controller
- Abstraction: Controller (buttons, joysticks)
- Implementation: Different consoles (Xbox, PlayStation, Switch)
โ You can use a controller to operate different consoles if they speak the same "control" language.
๐ฅ๏ธ 2. UI Themes
- Abstraction: UI Components (Button, Modal, Card)
- Implementation: Light Theme, Dark Theme, Neon Theme
โ You can swap the theme without rewriting components.
๐ 3. Vehicle and Engine
- Abstraction: Vehicle (Car, Truck)
- Implementation: Engine (PetrolEngine, ElectricEngine)
โ You can change engines without rebuilding the whole vehicle class.
๐ฅ๏ธ TypeScript Code Example โ Remote Control and Devices
Imagine:
- Remote controls devices (TV, Radio)
- Devices can be switched on/off independently.
1. Define the Implementation Interface
// Bridge Interface
interface Device {
turnOn(): void;
turnOff(): void;
}
2. Concrete Implementations
class TV implements Device {
turnOn() {
console.log("TV is now ON");
}
turnOff() {
console.log("TV is now OFF");
}
}
class Radio implements Device {
turnOn() {
console.log("Radio is now ON");
}
turnOff() {
console.log("Radio is now OFF");
}
}
3. Define the Abstraction
class RemoteControl {
constructor(protected device: Device) {}
turnDeviceOn() {
this.device.turnOn();
}
turnDeviceOff() {
this.device.turnOff();
}
}
4. Use It
const tv = new TV();
const radio = new Radio();
const tvRemote = new RemoteControl(tv);
tvRemote.turnDeviceOn(); // TV is now ON
const radioRemote = new RemoteControl(radio);
radioRemote.turnDeviceOff(); // Radio is now OFF
๐ฏ Why Use Bridge Pattern?
โ
Reduce code duplication
โ
Separate concerns (logic vs. implementation)
โ
Swap implementations easily (like device types, database drivers, themes)
โ
Extend without fear (add new devices or new remote functions separately)
โ Real-World Practical Uses of Bridge
Real-world example | Bridge usage |
---|---|
Database Drivers | Abstract DatabaseClient (PostgreSQL, MongoDB, MySQL) |
Payment Gateways | Abstract PaymentService (Stripe, PayPal, Apple Pay) |
Cloud Storage | Abstract StorageService (AWS S3, Google Cloud, Azure Blob) |
Frontend Themes | Abstract Theme (Light, Dark, Custom) |
Media Players | Abstract Player (MP3, MP4, WAV) |
๐ Visual Diagram
RemoteControl (Abstraction)
|
[uses]
โ
TV / Radio (Implementation)
โก๏ธ RemoteControl doesnโt care what device it controls, as long as it matches the Device interface.
๐ฆ Key Pattern Structure (Quick Summary)
// Implementation Interface
interface Implementor { method(): void; }
// Concrete Implementation
class ConcreteImplementorA implements Implementor { method() {} }
class ConcreteImplementorB implements Implementor { method() {} }
// Abstraction
class Abstraction {
constructor(protected implementor: Implementor) {}
operation() {
this.implementor.method();
}
}
๐ Important Tip for Senior-Level Usage
When designing large systems:
- Use Bridge if your abstractions and implementations both need to grow independently.
- It's better than subclass explosion (too many hardcoded variations).
โ Flexible, Extensible, and SOLID-friendly!
๐ Final Summary in One Line
"Bridge pattern separates what you do from how you do it."
Top comments (0)