Bridge Pattern in C#:
Decoupling Abstraction from Implementation
Bridge Pattern in C#:
Decoupling Abstraction from Implementation

In software design, we sometimes face classes that grow into a mess of subclasses due to multiple variations (e.g., shape + color, or device + remote control). The Bridge Pattern helps solve this problem by decoupling abstraction from implementation, letting them evolve independently.
This article explains the Bridge Pattern in C#, with examples and best practices.
What is the Bridge Pattern?
The Bridge Pattern is a structural design pattern that separates an abstraction from its implementation. Instead of binding them permanently, the pattern lets you combine different abstractions with different implementations dynamically.
Think of it like a TV and its remote control:
- The TV is the implementation (it knows how to turn on/off, change channels).
- The Remote is the abstraction (it provides user-friendly control). The Remote doesn’t care if it controls a Samsung or LG TV — it just bridges the commands.
UML Diagram
- Abstraction → High-level control (Remote)
- RefinedAbstraction → Specialized version of abstraction
- Implementor → Interface for low-level implementation (Device)
- ConcreteImplementor → Specific implementation (TV, Radio)

Example: Remote Control & Devices
Step 1 — Implementor (Device interface)
public interface IDevice
{
void TurnOn();
void TurnOff();
void SetVolume(int volume);
}
Step 2 — Concrete Implementors
public class Tv : IDevice
{
public void TurnOn() => Console.WriteLine("TV is ON");
public void TurnOff() => Console.WriteLine("TV is OFF");
public void SetVolume(int volume) => Console.WriteLine($"TV volume set to {volume}");
}
public class Radio : IDevice
{
public void TurnOn() => Console.WriteLine("Radio is ON");
public void TurnOff() => Console.WriteLine("Radio is OFF");
public void SetVolume(int volume) => Console.WriteLine($"Radio volume set to {volume}");
}
Step 3 — Abstraction (Remote Control)
public class RemoteControl
{
protected IDevice _device;
public RemoteControl(IDevice device)
{
_device = device;
}
public virtual void TurnOn() => _device.TurnOn();
public virtual void TurnOff() => _device.TurnOff();
public virtual void SetVolume(int volume) => _device.SetVolume(volume);
}
Step 4 — Refined Abstraction
public class AdvancedRemote : RemoteControl
{
public AdvancedRemote(IDevice device) : base(device) { }
public void Mute()
{
Console.WriteLine("Device muted");
_device.SetVolume(0);
}
}
Step 5 — Client Code
class Program
{
static void Main()
{
IDevice tv = new Tv();
RemoteControl remote = new RemoteControl(tv);
remote.TurnOn();
remote.SetVolume(15);
IDevice radio = new Radio();
AdvancedRemote advancedRemote = new AdvancedRemote(radio);
advancedRemote.TurnOn();
advancedRemote.Mute();
}
}
Another Example

public static void DemonstrateBridge()
{
Console.WriteLine("BRIDGE PATTERN - Device Control System");
IDevice radio = new Radio();
var remote = new RemoteControl(radio);
remote.TogglePower();
remote.VolumeUp();
}
public interface IDevice
{
bool IsEnabled(); void Enable(); void Disable();
int GetVolume(); void SetVolume(int volume);
}
public class Radio : IDevice
{
private bool _on = false; private int _volume = 30;
public bool IsEnabled() => _on;
public void Enable() { _on = true; Console.WriteLine("Radio ON"); }
public void Disable() { _on = false; Console.WriteLine("Radio OFF"); }
public int GetVolume() => _volume;
public void SetVolume(int volume) { _volume = volume; Console.WriteLine($"Volume: {volume}%"); }
}
public class RemoteControl
{
private IDevice device;
public RemoteControl(IDevice device) => this.device = device;
public void TogglePower()
{
if (device.IsEnabled()) device.Disable(); else device.Enable();
}
public void VolumeUp() => device.SetVolume(device.GetVolume() + 10);
}
Benefits of the Bridge Pattern
✅ Avoids class explosion when combining multiple dimensions (e.g., Shape + Color). ✅ Abstractions and implementations can evolve independently. ✅ Promotes composition over inheritance. ✅ Cleaner and more maintainable design.
Real-World Examples in .NET
- ILogger with providers → Abstraction (
ILogger) and implementation (ConsoleLogger,FileLogger). - DbProviderFactory → Abstracts database access, concrete providers implement specifics (SQL Server, Oracle).
- Dependency Injection → Often achieves bridge-like separation between interface and implementation.
When to Use the Bridge Pattern
- When you need to separate abstraction (high-level logic) from implementation (low-level operations).
- When your class hierarchy explodes due to combinations of features.
- When you want to switch implementations at runtime.
Conclusion
The Bridge Pattern is ideal when dealing with multi-dimensional variations in class hierarchies. It helps keep code flexible, promotes separation of concerns, and prevents rigid designs.
Next time you’re tempted to create dozens of subclasses to cover all variations, consider using the Bridge Pattern instead.
👉 Coming up next in this series: Composite Pattern in C#
✅ Full source code will be available here: hassan9810/Design.Patterns.Complete.Guide
메타데이터
- post_id
- 8364d1096b2e
- slug
- bridge-pattern-in-c-8364d1096b2e
- url
- https://medium.com/@hassan9810/bridge-pattern-in-c-8364d1096b2e
- canonical_url
- https://medium.com/@hassan9810/bridge-pattern-in-c-8364d1096b2e
- author_url
- https://medium.com/@hassan9810
- status
- ok
- fetched_at
- 2026-08-09 21:07:04