Understanding and Implementing Bridge Pattern in C#

Let us discuss “Bridge Pattern” in this article. When we think about bridge pattern the first thing that come to our mind is “it is some kind of bridge between two different implementations”. But this is not true. The above mentioned This is the task of Adapter pattern which is discussed here. But to talk about bridge, this pattern is designed specifically to let the abstraction and the implementation vary independently.

Background

GoF defines Bridge Pattern as “Decouple an abstraction from its implementation so that the two can vary independently.”

The best example for where this pattern can be used is the use of plugins or driver. If we have an application that can take use of any specific driver then we can use bridge pattern. A classic example of a scenario where this pattern could be used in a Video Configuration selection screen of a game like “Half-life”. This screen gives the user an option to run the game in OpenGL, Direct3Dor software mode. When the user makes a selection then we can use a concrete implementation specific to the selection and not effect the abstraction at all.

Let us visualize the bridge pattern now.

bridge

Now lets us see what each of these components in this class diagram represents.

  • Implementor: This interface provides preliminary operations that the all the plugins should provide.
  • ConcreteImplementor: These are the actual classes that implements the Implementorinterface. These classes will be used selectively like plugins.
  • Abstraction: This class provides an abstraction to the clients. The clients will continue to use this abstraction without even caring about what actual plugin i.e. ConcreteImplementoris being selected internally.
  • RefinedAbstraction: This class will implement the actual functionality if Abstraction class. Selecting the appropriate ConcreteImplementoris the responsibility of this class.

 

Using the Code

let us now try to implement a small example using bridge pattern. Let us think of an imaginary smart TV that gives the user a possibility of playing local cable TV, a local satellite TV or an IPTV source. Here the user can request TV guide from the selected source. He can also choose to play the selected TV source.

So from the TV’s perspective the abstraction for getting the guide and play the TV. The actual implementation will differ for each source. So let us go ahead and first define the abstraction that each TV source will provide i.e. The Implementorfrom the above diagram.

Let us now define the ConcreteImplementorsfor each TV source.

So we can see that each ConcreteImplementorprovide the same abstraction but the actual implementation differs (Right now we have dummy messages to show the different implementations).

Let us now implement the RefinedAbstractioni.e. The actual TV class that will use these ConcreteImplementorsto perform the playback. (For Simplicity, I have merger Abstractionand RefinedAbstractionin single class without any interface)

Next thing would be to use the appropriate implementation based on user selection. So let us give the user a choice to select the appropriate TV source and then get the TV guide from that source and even start playing that source.

Now the user can select the TV source and each TV source will have its own implementation but can be used with the same abstraction like a plugin based architecture.The interface for TV source now is totally independent of the implementations of each TV source.

Let us run the application and select IPTV as the source

running

Before concluding our discussion let us look at the class diagram of our application and map it with the class diagram of bridge pattern shown above.

myBridge

Point of Interest

Since the interface are more stable (i.e less probability of getting changed) than the implementation it sounds like a good idea to put the interfaces of a class separate from the implementation.

Download sample code for this article: BridgeTest