Problem :
Let’s say we want to communicate from system A to system B. ( Device and Remote ), Device can be anything (TV, fan, sensor), similarly for remote.
#include <iostream>
using namespace std;
// Each device has its own remote implementation
// ---- TV Remotes ----
class BasicTVRemote {
public:
void pressButton() {
cout << "Basic Remote: TV turned on\n";
}
};
class AdvancedTVRemote {
public:
void pressButton() {
cout << "Advanced Remote: TV voice command activated\n";
}
};
// ---- Fan Remotes ----
class BasicFanRemote {
public:
void pressButton() {
cout << "Basic Remote: Fan turned on\n";
}
};
class AdvancedFanRemote {
public:
void pressButton() {
cout << "Advanced Remote: Fan turned on with timer\n";
}
};
// ---- Main function ----
int main() {
BasicTVRemote basicTV;
AdvancedTVRemote advTV;
BasicFanRemote basicFan;
AdvancedFanRemote advFan;
basicTV.pressButton();
advTV.pressButton();
basicFan.pressButton();
advFan.pressButton();
return 0;
}
#include <iostream>
#include <memory>
using namespace std;
// ---- Implementor Interface ----
class Device {
public:
virtual void turnOn() = 0;
virtual ~Device() = default;
};
// ---- Concrete Devices ----
class TV : public Device {
public:
void turnOn() override {
cout << "TV turned on\n";
}
};
class Fan : public Device {
public:
void turnOn() override {
cout << "Fan turned on\n";
}
};
// ---- Abstraction ----
class RemoteControl {
protected:
Device* device; // Bridge
public:
RemoteControl(Device* d) : device(d) {}
virtual void pressButton() = 0;
virtual ~RemoteControl() = default;
};
// ---- Refined Abstractions ----
class BasicRemote : public RemoteControl {
public:
BasicRemote(Device* d) : RemoteControl(d) {}
void pressButton() override {
cout << "Basic Remote: ";
device->turnOn();
}
};
class AdvancedRemote : public RemoteControl {
public:
AdvancedRemote(Device* d) : RemoteControl(d) {}
void pressButton() override {
cout << "Advanced Remote with voice: ";
device->turnOn();
}
};
// ---- Main function ----
int main() {
TV tv;
Fan fan;
BasicRemote basicTV(&tv);
AdvancedRemote advTV(&tv);
BasicRemote basicFan(&fan);
AdvancedRemote advFan(&fan);
basicTV.pressButton();
advTV.pressButton();
basicFan.pressButton();
advFan.pressButton();
return 0;
}
You already have:
- 2 Devices:
TV,Fan - 2 Remotes:
BasicRemote,AdvancedRemote
Now:
- You want to add a new device →
Light - You want to add a new remote →
GestureRemote
🔁 Comparison Table: Scalability Impact
| Action | Without Bridge (Tightly Coupled) | With Bridge Pattern |
|---|---|---|
| 📦 Classes you already have | BasicTVRemote, AdvancedTVRemote,BasicFanRemote, AdvancedFanRemote | TV, Fan, BasicRemote, AdvancedRemote |
➕ Add new device Light | Add:BasicLightRemote, AdvancedLightRemote → 2 new classes | Add: Light only → 1 new class |
➕ Add new remote GestureRemote | Add:GestureTVRemote, GestureFanRemote, GestureLightRemote → 3 new classes | Add: GestureRemote only → 1 new class |
| 🧮 Total class count after both changes | 4 (existing) + 2 + 3 = 9 | 4 (existing) + 1 + 1 = 6 |
Imagine you have a remote control for a device (like a TV). The remote control doesn’t care what kind of device it’s controlling (TV, stereo, etc.), it just sends signals. The device itself doesn’t care what kind of remote control is being used (physical remote, app, etc.), it just receives signals and reacts accordingly.
The Bridge Design Pattern is like having a universal adapter between two separate things. These things can work with different partners as long as they speak the same “language” (interface). This allows for more flexibility and easier changes in the future.
Bridge Design Pattern is a structural design pattern that separates the abstraction (what needs to be done) from the implementation (how it’s done) by:
- Defining Interfaces: It creates interfaces (using abstract classes or pure virtual classes) that define the operations (functions) that concrete classes must implement. These interfaces act as the “language” that different parts of the code can understand.
- Separating Implementations: Concrete classes implement these interfaces, providing the actual functionality for the operations. This separation allows for independent development and modification of the abstraction and implementation.

class IDevice {
public:
virtual ~IDevice() = default;
virtual void on() = 0;
virtual void off() = 0;
virtual void volumeUp() = 0;
virtual void volumeDown() = 0;
};
class IRemote {
public :
virtual ~IRemote() = default;
virtual void press1() = 0;
virtual void press2() = 0;
};
class TV : public IDevice {
public:
void on();
void off();
void volumeUp() {}
void volumeDown() {}
};
class Radio : public IDevice {
public:
void on();
void off();
void volumeUp() {}
void volumeDown() {}
};
class IRRemote : public IRemote {
public:
IRRemote(IDevice &device) : mDevice(device) {
cout << "IR remote created for TV" <<endl;
}
virtual void press1();
virtual void press2();
private:
IDevice & mDevice;
};
class BluetoothRemote : public IRemote {
public:
BluetoothRemote(IDevice &device) : mDevice(device) {
cout << "bluetooth remote created for TV" <<endl;
}
virtual void press1();
virtual void press2();
private:
IDevice & mDevice;
};
void TV::on() {
cout <<" turn on TV" <<endl;
}
void TV::off() {
cout <<" turn off TV" <<endl;
}
void Radio::on() {
cout <<" turn on Radio" <<endl;
}
void Radio::off() {
cout <<" turn off Radio" <<endl;
}
void IRRemote::press1() {
cout <<" use ir remote ";
mDevice.on();
}
void IRRemote::press2() {
cout <<" use ir remote ";
mDevice.off();
}
void BluetoothRemote::press1() {
cout <<" use bt remote ";
mDevice.on();
}
void BluetoothRemote::press2() {
cout <<" use bt remote ";
mDevice.off();
}
class UniversalRemote {
unique_ptr<IDevice> device;
unique_ptr<IRemote> remote;
public:
UniversalRemote (unique_ptr<IDevice> &d, unique_ptr<IRemote> &r) : device(std::move(d)), remote (std::move(r)) {
}
void press1() {
// cout <<" universal remote press1 " <<endl;
remote->press1();
}
void press2() {
//cout <<" universal remote press2 " <<endl;
remote->press2();
}
void setRemote(unique_ptr<IRemote>& r) {
cout <<" remote changed " << endl;
remote = std::move(r);
}
};
int main() {
unique_ptr<IDevice> dev = make_unique<TV>();
unique_ptr<IRemote> rem = make_unique<BluetoothRemote>(*dev);
unique_ptr<IRemote> rem1 = make_unique<IRRemote>(*dev);
UniversalRemote ur(dev, rem);
ur.press1();
ur.press2();
ur.setRemote(rem1);
ur.press1();
ur.press2();
}
Follow more posts @ https://jdecodes.wordpress.com
My all design pattern articles :
- https://jdecodes.wordpress.com/2024/07/13/builder-design-pattern/
- https://jdecodes.wordpress.com/2024/07/13/command-design-pattern/
- https://jdecodes.wordpress.com/2024/07/13/iterator-design-pattern/
- https://jdecodes.wordpress.com/2024/07/13/mediator-design-pattern/
- https://jdecodes.wordpress.com/2024/07/19/state-design-pattern/
- https://jdecodes.wordpress.com/2024/07/19/memento-design-pattern/
- https://jdecodes.wordpress.com/2024/07/19/observer-design-pattern/
- https://jdecodes.wordpress.com/2024/07/19/strategy-pattern/
- https://jdecodes.wordpress.com/2024/07/20/visitor-design-pattern/
- https://jdecodes.wordpress.com/2024/07/20/adapter-desing-pattern/
- https://jdecodes.wordpress.com/2024/07/20/bridge-design-pattern/
- https://jdecodes.wordpress.com/2024/07/22/composite-desing-pattern/
- https://jdecodes.wordpress.com/2024/07/22/facade-design-pattern/
- https://jdecodes.wordpress.com/2024/07/22/decorater-design-pattern/
Leave a comment