Bridge Design Pattern in C#

Bridge Design Pattern in C# with Real-time Example

In this article, I am going to discuss the Bridge Design Pattern in C# with some examples. Please read our previous article where we discussed the Decorator Design Pattern in C# with examples. The Bridge Design Pattern falls under the category of Structural Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is the Bridge Design Pattern?
  2. Understanding Abstraction and Implementation in detail.
  3. Understanding the Bridge Design Pattern with Real-time example.
  4. Implementation of the Bridge Design Pattern in C#.
  5. Understanding the class diagram of the Bridge Design Pattern.
  6. When do we need to use the Bridge Design Pattern in real-time applications?
What is Bridge Design Pattern in C#?

As per the Gang of Four definitions, the Bridge Pattern “Decouples an abstraction from its implementation so that the two can vary independently“.

In the bridge design pattern, there are 2 parts. The first part is the abstraction and the second part is the implementation. The bridge design pattern allows the abstraction and implementation to be developed independently and the client code can access only the abstraction part without being concerned about the implementation part.

The Bridge Design Pattern separates the abstraction hierarchy and the implementation hierarchy in two different layers so that change in one hierarchy will not affect the development or functionality of other hierarchy.

Understand the Definition of Bridge Design Pattern:

In order to understand the definition, please have a look at the following image. Suppose we have one requirement to save or delete an object in the persistence. Here, we can either save the object into a File System or into a database. So, on the right-hand side, you can see two implementers. The FileSystemPersistenceImplementor is used to save the object into a file whereas the DatabasePersistenceImplementor is used to save the object into a database. So, we can use any one of the above implementors to save an object.

Understanding the definitions of Bridge Design Pattern

So, as per the Bridge design pattern, the abstraction and implementation should be in a separate layer. Here, the persistence is the abstraction layer and persistence implementation is the implementation layer. Now, if you want to add new implementation or if you want to remove any implementation, then it will not affect the Abstraction layer. This is the advantage of the bridge design pattern.

The abstract persistence layer will use any of the implementers to save or delete an object and the client will only use the abstraction to save or delete the object. Now if you read the definitions then you can easily understand the bridge design pattern.

Real-time Example of Bridge Design Pattern:

In the Bridge Design Pattern, there are two layers. The first layer is the Abstraction layer and the second layer is the Implementation Layer. If I do make any changes in the Implementation Layer, then it won’t affect the Abstraction Layer. Similarly, if I made any changes in the Abstraction Layer, then it won’t affect the Implementation layer.

Please have a look at the following image. On the left-hand side, you can see the abstraction. Suppose, you want to turn on the TV or turn off the TV, then what you can do here is, you can use the Remote Control to turn On/Off the TV. The implementation will be done by the original TV implementer. So, in this case, Samsung TV or Sony TV will implement the turn On or turn Off functionality. So, the abstraction will use one of the implementers to turn on or turn off the TV.

Real-time Example of Bridge Design Pattern

Suppose, later you want to add new implementation then you can do this in the implementation layer. For example, you can add new TV (for example Panasonic TV) in the implementation layer which will not affect the Abstraction layer. Like that, you can also add a new Panasonic TV remote in the abstraction layer without affecting the implementation layer. So, this is one of the best examples of bridge design pattern.

Note: First we will implement the example using the bridge design pattern and then we will try to understand the class diagram of the Bridge Design Pattern by comparing it with our example.

Implementation of Bridge Design Pattern in C#:

Let us implement the above example step by step using the bridge design pattern in C#.

Step1: Creating Abstract LED TV

Create an interface with the name LEDTV and then copy and paste the following code in it. This interface has three methods (SwitchOff, SwitchOn, and SetChannel). This interface will be implemented by the implementation classes.

namespace BridgeDesignPattern
{
    public interface LEDTV
    {
         void SwitchOn();
         void SwitchOff();
         void SetChannel(int channelNumber);
    }
}
Step2: Creating Concrete LED TV

In our example, we are going to create two concrete classes i.e. SamsungLedTv and SonyLedTV.

SamsungLedTv

Create a class file with the name SamsungLedTv and then copy and paste the following code in it. This class implements the LEDTV interface and provides implementations for SwitchOn, SwitchOff, and SetChannel methods. Using the SwitchOn method we can turn On the Samsung TV. Using the SwitchOff method we can turn Off the Samsung TV and using the SetChannel method we can change the channel number of the Samsung TV.

using System;
namespace BridgeDesignPattern
{
    public class SamsungLedTv : LEDTV
    {
        public void SwitchOn()
        {
            Console.WriteLine("Turning ON : Samsung TV");
        }
        public void SwitchOff()
        {
            Console.WriteLine("Turning OFF : Samsung TV");
        }

        public void SetChannel(int channelNumber)
        {
            Console.WriteLine("Setting channel Number " + channelNumber + " on Samsung TV");
        }
    }
}
SonyLedTv:

Create a class file with the name SonyLedTv and then copy and paste the following code in it. This class also implements the LEDTV interface and also provides implementations for SwitchOn, SwitchOff, and SetChannel methods. Using the SwitchOn method we can turn On the Sony TV. Using the SwitchOff method we can turn Off the Sony TV and using the SetChannel method we can change the channel number of the Sony TV.

using System;
namespace BridgeDesignPattern
{
    public class SonyLedTv : LEDTV
    {
        public void SwitchOn()
        {
            Console.WriteLine("Turning ON : Sony TV");
        }
        public void SwitchOff()
        {
            Console.WriteLine("Turning OFF : Sony TV");
        }

        public void SetChannel(int channelNumber)
        {
            Console.WriteLine("Setting channel Number " + channelNumber + " on Sony TV");
        }
    }
}
Step3: Creating Abstract Remote Control

Create a class with the name AbstractRemoteControl and then copy and paste the following code in it. This is going to be an abstract class having three abstract methods (SwitchOn, SwitchOff, and SetChannel). It has one protected variable ledTv which is going to be available to subclasses.

namespace BridgeDesignPattern
{
   public abstract class AbstractRemoteControl
    {
        protected LEDTV ledTv;

        protected AbstractRemoteControl(LEDTV ledTv)
        {
            this.ledTv = ledTv;
        }

        public abstract void SwitchOn();
        public abstract void SwitchOff();
        public abstract void SetChannel(int channelNumber);
    }
}
Step4: Creating Concrete Remote Control

Here, we are going to create two concrete remote control classes i.e. SamsungRemoteControl and SonyRemoteControl

SamsungRemoteControl:

Create a class file with the name SamsungRemoteControl and then copy and paste the following code in it. This is a concrete class and it implements the abstract AbstractRemoteControl class and provides the implementation for SwitchOn, SwitchOff, and SetChannel method. In the constructor, we have to attach the LEDTV which we want to access remotely.

namespace BridgeDesignPattern
{
    public class SamsungRemoteControl : AbstractRemoteControl
    {
        public SamsungRemoteControl(LEDTV ledTv) : base(ledTv)
        {
        }
        
        public override void SwitchOn()
        {
            ledTv.SwitchOn();
        }

        public override void SwitchOff()
        {
            ledTv.SwitchOff();
        }

        public override void SetChannel(int channelNumber)
        {
            ledTv.SetChannel(channelNumber);
        }
    }
}
SonyRemoteControl:

Create a class file with the name SonyRemoteControl and then copy and paste the following code in it. This is also going to be a concrete class and also implement the AbstractRemoteControl class and provides the implementation for SwitchOn, SwitchOff, and SetChannel method. In the constructor, you have to pass the LEDTV which you want to access remotely.

namespace BridgeDesignPattern
{
    public class SonyRemoteControl : AbstractRemoteControl
    {
        public SonyRemoteControl(LEDTV ledTv) : base(ledTv)
        {
        }

        public override void SwitchOn()
        {
            ledTv.SwitchOn();
        }

        public override void SwitchOff()
        {
            ledTv.SwitchOff();
        }

        public override void SetChannel(int channelNumber)
        {
            ledTv.SetChannel(channelNumber);
        }
    }
}
Step5: Client class

The client class has the Main method. So, please modify the Main method as shown below. Here, first, we are using the SonyRemoteControl and attaching the SonyLedTv so that we can access Sony Led TV remotely (i.e. Turn On, Change Channel and Turn Off). Like that we can also do the same thing using SamsungRemoteControl to access the SansungLedTv remotely.

using System;
namespace BridgeDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            SonyRemoteControl sonyRemoteControl = new SonyRemoteControl(new SonyLedTv());
            sonyRemoteControl.SwitchOn();
            sonyRemoteControl.SetChannel(101);
            sonyRemoteControl.SwitchOff();
            
            Console.WriteLine();

            SamsungRemoteControl samsungRemoteControl = new SamsungRemoteControl(new SamsungLedTv());
            samsungRemoteControl.SwitchOn();
            samsungRemoteControl.SetChannel(202);
            samsungRemoteControl.SwitchOff();
            
            Console.ReadKey();
        }
    }
}

Output:

Implementation of Bridge Design Pattern in C#

Now, I hope you understand the Bridge Design Pattern. So, let us try to understand the class diagram and the different components or participants involved in the Bridge Design Patter.

Understanding the Class Diagram of Bridge Design Pattern:

Please have a look at the following image to understand the class diagram of the Bridge Design Pattern.

Class Diagram of Bridge Design Pattern

As shown in the above image, the bridge design pattern consists of four participants. They are as follows.

Implementer:

This is an interface and this interface must be implemented by all the implementation classes. This interface is going to act as a bridge between the abstraction class and the implementer class. In our example, it is the LEDTV interface.

ConcreteImplementationA / ConcreteImplementaionB:

These are going to be classes and implements the Implementor (LEDTV) interface. In our example, it is our SamsungLedTv and SonyLedTv class. These classes contain the concrete implementation of all the operations (in our example implementation for SwitchOn, SwitchOff, and SetChannel methods).

Abstraction:

This is going to be an abstract class. In our example, it is the AbstractRemoteControl class. It defines the methods (in our example SwitchOn, SwitchOff, and SetChannel) for the client code to call. The protected implementer variable (in our example it is the ledTv variable) holds a reference to the object that performs the implementation.

ConcreteAbstraction / RefinedAbstraction:

The ConcreteAbstraction are the concrete classes that are inherited from the Abstraction abstract class. In our example, it is the SamsungRemoteControl and SonyRemoteControl.

When do we need to use the Bridge Design Pattern in C# real-time applications?

We need to use the Bridge Design Pattern when

  1. We want to hide the implementation details from the client.
  2. We want the selection or switching of the implementation is at runtime rather than design time.
  3. We want both the abstraction and implementation classes to be extensible by the subclasses.
  4. We want to avoid a tight coupling binding between an abstraction and its implementation. 
  5. The changes in the implementation of an abstraction should have no impact on clients.
  6. When we want to share an implementation among multiple objects and this should be hidden from the client.  

In the next article, I am going to discuss the Bridge Design Pattern Real-Time Example- Send Message using C#. Here, in this article, I try to explain the Bridge Design Pattern in C# step by step with some simple examples. I hope you understood the need and use of the Bridge Design Pattern in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *