Bridge Pattern in C#: Definition, Use Cases, Pros, Cons, and Examples
The Bridge Pattern in C# is a structural design pattern that separates abstraction from implementation so that both can evolve independently.
The Bridge Pattern is used to decouple an abstraction from its implementation by placing them into separate class hierarchies. Instead of tightly binding functionality to a specific implementation, the abstraction holds a reference to an implementation interface. This allows developers to extend abstractions and implementations independently without modifying existing code. The pattern is especially useful when multiple variations of abstractions and implementations exist and inheritance would otherwise lead to a large number of classes. In C#, the Bridge Pattern improves flexibility, scalability, and maintainability in complex systems.
Why We Use Bridge Pattern in C#?
We use the Bridge Pattern in C# to avoid class explosion caused by deep inheritance hierarchies. It helps separate high-level business logic from platform-specific or implementation-specific details. The pattern also improves extensibility by allowing abstractions and implementations to vary independently.
Main reasons for using it:
• Reduce tight coupling between abstraction and implementation
• Avoid excessive inheritance
• Improve maintainability
• Support runtime implementation switching
• Increase flexibility and scalability
• Follow SOLID design principles
When Should We Use Bridge Pattern in C#?
The Bridge Pattern should be used when:
• A class has multiple independent dimensions of variation
• You want abstraction and implementation to evolve separately
• Inheritance creates too many subclasses
• Runtime implementation switching is required
• Platform-independent systems are needed
• Changes in implementation should not affect client code
Typical programming problems solved by the Bridge Pattern:
• Cross-platform UI systems
• Rendering engines
• Device-driver communication
• Notification systems
• Database abstraction layers
• Messaging systems
• Multi-platform applications
Structure of Bridge Pattern in C#
| Component | Responsibility |
|---|---|
| Abstraction | Defines high-level control logic |
| Refined Abstraction | Extended abstraction functionality |
| Implementor | Defines implementation interface |
| Concrete Implementor | Provides actual implementation details |
| Client | Uses abstraction without depending on implementation |
Bridge Pattern Examples in C#
Example 1: Remote Control and TV
Different remote controls should work with different TV brands without creating many subclasses.
using System;
public interface ITV
{
void On();
void Off();
}
public class SamsungTV : ITV
{
public void On()
{
Console.WriteLine("Samsung TV turned ON");
}
public void Off()
{
Console.WriteLine("Samsung TV turned OFF");
}
}
public class SonyTV : ITV
{
public void On()
{
Console.WriteLine("Sony TV turned ON");
}
public void Off()
{
Console.WriteLine("Sony TV turned OFF");
}
}
public abstract class RemoteControl
{
protected ITV _tv;
protected RemoteControl(ITV tv)
{
_tv = tv;
}
public abstract void TogglePower();
}
public class BasicRemote : RemoteControl
{
public BasicRemote(ITV tv) : base(tv)
{
}
public override void TogglePower()
{
_tv.On();
_tv.Off();
}
}
class Program
{
static void Main()
{
RemoteControl remote =
new BasicRemote(new SamsungTV());
remote.TogglePower();
}
}
Example 2 — Notification System
Notifications should support multiple message types and delivery channels independently.
using System;
public interface IMessageSender
{
void SendMessage(string message);
}
public class EmailSender : IMessageSender
{
public void SendMessage(string message)
{
Console.WriteLine("Email: " + message);
}
}
public class SmsSender : IMessageSender
{
public void SendMessage(string message)
{
Console.WriteLine("SMS: " + message);
}
}
public abstract class Notification
{
protected IMessageSender _sender;
protected Notification(IMessageSender sender)
{
_sender = sender;
}
public abstract void Send(string message);
}
public class AlertNotification : Notification
{
public AlertNotification(IMessageSender sender)
: base(sender)
{
}
public override void Send(string message)
{
_sender.SendMessage("[ALERT] " + message);
}
}
class Program
{
static void Main()
{
Notification notification =
new AlertNotification(new EmailSender());
notification.Send("Server is down.");
}
}
Example 3 — Shape Rendering System
Shapes and rendering methods should vary independently.
using System;
public interface IRenderer
{
void RenderCircle(float radius);
}
public class VectorRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Drawing circle as vectors: {radius}");
}
}
public class RasterRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Drawing circle as pixels: {radius}");
}
}
public abstract class Shape
{
protected IRenderer _renderer;
protected Shape(IRenderer renderer)
{
_renderer = renderer;
}
public abstract void Draw();
}
public class Circle : Shape
{
private float _radius;
public Circle(IRenderer renderer, float radius)
: base(renderer)
{
_radius = radius;
}
public override void Draw()
{
_renderer.RenderCircle(_radius);
}
}
class Program
{
static void Main()
{
Shape shape =
new Circle(new VectorRenderer(), 10);
shape.Draw();
}
}
Most Common Real-World Use Cases of Bridge Pattern in C#
| Use Case | Description |
|---|---|
| Cross-Platform UI Frameworks | Separating UI controls from platform-specific rendering |
| Notification Systems | Supporting multiple notification types and delivery methods |
| Rendering Engines | Separating shapes from rendering technologies |
| Database Drivers | Decoupling database abstraction from providers |
| Device Controllers | Supporting multiple hardware implementations |
| Messaging Systems | Separating messages from transport protocols |
| Cloud Storage Systems | Abstracting storage logic from cloud providers |
Advantages of Using Bridge Pattern in C#
1. Reduces Class Explosion
Prevents excessive subclass creation caused by combining multiple dimensions.
2. Improves Flexibility
Abstractions and implementations can change independently.
3. Better Maintainability
Implementation changes do not affect client code.
4. Supports Runtime Switching
Implementations can be replaced dynamically.
5. Encourages Composition Over Inheritance
Uses object composition instead of large inheritance hierarchies.
6. Follows SOLID Principles
Especially:
• Open/Closed Principle
• Single Responsibility Principle
Disadvantages (Weak Points) of Bridge Pattern in C#
1. Increased Complexity
Adds extra abstraction layers and interfaces.
2. More Initial Design Effort
Requires careful architecture planning.
3. Harder for Small Projects
May be unnecessary overhead for simple systems.
4. More Classes
Introduces additional interfaces and implementations.
5. Learning Curve
Can be difficult for beginners to understand initially.
Bridge Pattern vs Similar Patterns
| Pattern | Main Purpose | Key Difference from Bridge | Typical Usage |
|---|---|---|---|
| Bridge | Separate abstraction from implementation | Allows independent evolution of both sides | Cross-platform systems |
| Adapter | Convert incompatible interfaces | Focuses on compatibility rather than separation | Legacy system integration |
| Decorator | Add functionality dynamically | Adds behavior instead of separating abstraction | Logging, caching, validation |
| Facade | Simplify subsystem usage | Provides simpler interface instead of abstraction separation | Complex frameworks |
| Strategy | Encapsulate interchangeable algorithms | Focuses on algorithm replacement | Sorting, payment methods |
Summary
The Bridge Pattern in C# is a powerful structural design pattern used to separate abstraction from implementation, enabling both to evolve independently. It is especially valuable in systems with multiple dimensions of variation, such as UI frameworks, rendering engines, and messaging platforms. By using composition instead of deep inheritance, the pattern improves scalability, flexibility, and maintainability. Although it introduces additional complexity and classes, it provides long-term architectural benefits in medium and large-scale applications.
Structural Patterns in C#
6. Adapter
7. Bridge
8. Composite
9. Decorator
10. Facade
11. Flyweight
12. Proxy