Bridge Design Pattern


Here, we will explain Bridge Design Pattern with example in C#

Bridge Design Pattern

The Bridge Design Pattern is a structural pattern that decouples an abstraction from its implementation, allowing both to vary independently. This is useful when you want to avoid a permanent binding between an abstraction and its implementation, enabling flexibility in the system design.

Decoupling

Decoupling an abstraction means separating the high-level concepts (abstractions) of a system from their low-level details (implementations). In simpler terms, it allows the abstract part of the system (the general idea or interface) to operate independently of the concrete part (how it's actually done).

Example - let's say you have an interface for a Shape (like a circle or rectangle). The details of how each shape is drawn (e.g., with OpenGL, DirectX) are the implementation. By decoupling, you make sure that the Shape abstraction is independent of how the drawing happens, so the shape can use any drawing method without the need to change the shape code.

A real-world example could be a remote control and television of Bridge Design Pattern. We will explain in detail lator part of the article.

bridge Design Pattern

Advantages of the Bridge Pattern

  • Decoupling of Abstraction and Implementation - The pattern separates the abstraction and the implementation, allowing changes to either without affecting the other.
  • Improved Maintainability - Modifications in one part of the system (e.g., abstraction or implementation) don’t affect the other part, making the system easier to maintain.
  • Enhanced Extensibility - Both the abstraction and implementation can be extended independently, making it easier to add new functionality.
  • Promotes Open/Closed Principle - The Bridge pattern allows adding new abstractions and implementations without modifying existing code.
  • Improved Reusability - It fosters reuse by allowing different abstractions to use the same implementation.

When to Use the Bridge Pattern

  • When you need to decouple abstraction from implementation - Use it when you want to be able to modify or extend either the abstraction or implementation without affecting the other.
  • When classes grow exponentially due to inheritance - If you have a scenario where you would end up with many subclasses because of different combinations of abstractions and implementations.
  • When you want to avoid a permanent binding between abstraction and implementation - When you need flexibility in switching implementations during runtime.
  • When abstraction and implementation need to evolve independently - The pattern is useful when both abstraction and implementation may change frequently or need to scale independently.

Problems in a System Without Bridge

  • Tight Coupling - Without the Bridge pattern, abstractions and implementations would be tightly coupled, making it hard to change one without affecting the other.
  • Class Explosion - Without the Bridge pattern, you would need multiple concrete classes to represent combinations of abstractions and implementations, leading to a class hierarchy explosion.
  • Limited Flexibility - Without the decoupling, adding new implementations or abstractions could require significant modifications to existing code.
  • Difficult Maintainability - In a tightly coupled system, changes in one part of the system would require cascading changes, making maintenance difficult.

Real-World Example of Bridge Pattern

A real-world example could be a remote control and television. The remote control (abstraction) can work with different television brands (implementation). The remote control has standard operations (like TurnOn, TurnOff), and each brand’s television can have its unique implementation of how those operations are performed.

  • Abstraction - The remote control with methods like TurnOn, TurnOff.
  • Implementation - Different television brands, each with their own behavior for turning on and off.

In this scenario, the remote control does not need to know how the television works internally. It interacts through a common interface, making it easy to extend both the remote control and the television independently.

+--------------------------+
|    ITelevision           |
|--------------------------|
| + On()                   |
| + Off()                  |
| + SwitchChannel(int)     |
+--------------------------+
       ^       ^
       |       |
+-------------------+   +-------------------+
| SonyTelevision    |   | SamsungTelevision |
|-------------------|   |-------------------|
| + On()            |   | + On()            |
| + Off()           |   | + Off()           |
| + SwitchChannel() |   | + SwitchChannel() |
+-------------------+   +-------------------+

         +--------------------------+
         |    RemoteControl         |
         |--------------------------|
         | - television: ITelevision|
         |--------------------------|
         | + TurnOn()               |
         | + TurnOff()              |
         +--------------------------+
                     ^
                     |
                     |
+-------------------------------+
|    AdvancedRemoteControl      |
+-------------------------------+
| + SetChannel(int channel)     |
+-------------------------------+
| Inherits TurnOn()             |
| Inherits TurnOff()            |
+-------------------------------+

Here is a C# implementation of the Bridge Pattern using the example of a remote control (abstraction) and different television brands (implementation).

using System;

// Abstraction: Remote control
abstract class RemoteControl
{
    protected ITelevision television;

    public RemoteControl(ITelevision tv)
    {
        television = tv;
    }

    public abstract void TurnOn();
    public abstract void TurnOff();
}

// Refined Abstraction: Advanced remote control with extra functionality
class AdvancedRemoteControl : RemoteControl
{
    public AdvancedRemoteControl(ITelevision tv) : base(tv) { }

    public override void TurnOn()
    {
        television.On();
    }

    public override void TurnOff()
    {
        television.Off();
    }

    public void SetChannel(int channel)
    {
        television.SwitchChannel(channel);
    }
}

// Implementor: Interface for the television
interface ITelevision
{
    void On();
    void Off();
    void SwitchChannel(int channel);
}

// Concrete Implementations: Different brands of televisions
class SonyTelevision : ITelevision
{
    public void On()
    {
        Console.WriteLine("Sony TV is turned ON.");
    }

    public void Off()
    {
        Console.WriteLine("Sony TV is turned OFF.");
    }

    public void SwitchChannel(int channel)
    {
        Console.WriteLine($"Sony TV switched to channel {channel}.");
    }
}

class SamsungTelevision : ITelevision
{
    public void On()
    {
        Console.WriteLine("Samsung TV is turned ON.");
    }

    public void Off()
    {
        Console.WriteLine("Samsung TV is turned OFF.");
    }

    public void SwitchChannel(int channel)
    {
        Console.WriteLine($"Samsung TV switched to channel {channel}.");
    }
}

// Client code
class Program
{
    static void Main(string[] args)
    {
     // Creating a Sony TV with a remote control
     ITelevision sonyTv = new SonyTelevision();
     RemoteControl remoteSony = new AdvancedRemoteControl(sonyTv);

     remoteSony.TurnOn(); // Output: Sony TV is turned ON.
     ((AdvancedRemoteControl)remoteSony).SetChannel(5); // Output: Sony TV switched to channel 5.
     remoteSony.TurnOff(); // Output: Sony TV is turned OFF.

     // Creating a Samsung TV with a remote control
     ITelevision samsungTv = new SamsungTelevision();
     RemoteControl remoteSamsung = new AdvancedRemoteControl(samsungTv);

     remoteSamsung.TurnOn(); // Output: Samsung TV is turned ON.
     ((AdvancedRemoteControl)remoteSamsung).SetChannel(10); // Output: Samsung TV switched to channel 10.
     remoteSamsung.TurnOff(); // Output: Samsung TV is turned OFF.
   }
}

Breakdown

  • Abstraction (RemoteControl) - This is the base class for the remote control. It has the methods TurnOn and TurnOff, which are common for all types of televisions.
  • Refined Abstraction (AdvancedRemoteControl) - A more specific implementation of the RemoteControl class that can handle advanced features like SetChannel.
  • Implementor (ITelevision) - This interface defines the methods that different brands of televisions must implement (i.e., On, Off, SwitchChannel).
  • Concrete Implementors (SonyTelevision and SamsungTelevision) - These are concrete classes implementing the ITelevision interface, representing specific brands of televisions with their own behavior.

Output

bridge Design Pattern

Applications of the Bridge Design Pattern

  • UI Toolkits - When you want to decouple the interface (e.g., buttons, windows) from the rendering engines (e.g., Windows, macOS).
  • Graphics and Rendering Libraries - Where rendering can be done through multiple platforms (e.g., OpenGL, DirectX), and the abstraction (shapes, objects) can evolve independently of the rendering engine.
  • Cross-Platform Software - In systems where different platforms or hardware use different implementations but need a common interface.
  • Database Systems - When different databases (MySQL, Oracle) are used, but the system needs to interact with them through a common interface.

Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question