Click here to Skip to main content
15,884,237 members
Articles / Programming Languages / C#

Understanding and Implementing Bridge Pattern in C#

Rate me:
Please Sign up or sign in to vote.
4.71/5 (21 votes)
3 Aug 2012CPOL3 min read 80.3K   674   22   10
This article discuss Bridge Pattern and try to demonstrate it using a simple application.

Introduction

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, Direct3D or 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. 

Image 1

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 Implementor interface. 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. ConcreteImplementor is being selected internally.
  • RefinedAbstraction: This class will implement the actual functionality if Abstraction class. Selecting the appropriate ConcreteImplementor is 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 Implementor from the above diagram.

C#
interface IVideoSource
{
	string GetTvGuide();
	string PlayVideo();
}

Let us now define the ConcreteImplementors for each TV source.

C#
class LocalCabelTv : IVideoSource
{
	const string SOURCE_NAME = "Local Cabel TV";

	string IVideoSource.GetTvGuide()
	{
		return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
	}

	string IVideoSource.PlayVideo()
	{
		return string.Format("Playing - {0}", SOURCE_NAME);
	}
}

class LocalDishTv : IVideoSource
{
	const string SOURCE_NAME = "Local DISH TV";

	string IVideoSource.GetTvGuide()
	{
		return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
	}

	string IVideoSource.PlayVideo()
	{
		return string.Format("Playing - {0}", SOURCE_NAME);
	}
}

class IPTvService : IVideoSource
{
	const string SOURCE_NAME = "IP TV";

	string IVideoSource.GetTvGuide()
	{
		return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
	}

	string IVideoSource.PlayVideo()
	{
		return string.Format("Playing - {0}", SOURCE_NAME);
	}
}

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

Let us now implement the RefinedAbstraction i.e. The actual TV class that will use these ConcreteImplementors to perform the playback. (For Simplicity, I have merger Abstraction and RefinedAbstraction in single class without any interface)

class MySuperSmartTV
{
	IVideoSource currentVideoSource = null;

	public IVideoSource VideoSource
	{
		get
		{
			return currentVideoSource;
		}
		set
		{
			currentVideoSource = value;
		}
	}

	public void ShowTvGuide()
	{
		if (currentVideoSource != null)
		{
			Console.WriteLine(currentVideoSource.GetTvGuide());
		}
		else
		{
			Console.WriteLine("Please select a Video Source to get TV guide from");
		}
	}

	public void PlayTV()
	{
		if (currentVideoSource != null)
		{
			Console.WriteLine(currentVideoSource.PlayVideo());
		}
		else
		{
			Console.WriteLine("Please select a Video Source to play");
		}
	}
}

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.

C#
class SuperSmartTvController
{
	static void Main(string[] args)
	{
		MySuperSmartTV myTv = new MySuperSmartTV();
					
		Console.WriteLine("Select A source to get TV Guide and Play");
		Console.WriteLine("1. Local Cable TV\n2. Local Dish TV\n3. IP TV");

		ConsoleKeyInfo input = Console.ReadKey();

		// Let us see what user has selected and select the video source accrodingly
		switch (input.KeyChar)
		{
			case '1':
				myTv.VideoSource = new LocalCabelTv();
				break;

			case '2':
				myTv.VideoSource = new LocalDishTv();
				break;

			case '3':
				myTv.VideoSource = new IPTvService();
				break;                
		}

		Console.WriteLine(); //some whitespace on output for readability

		//Let us show the TV guide from selected source
		myTv.ShowTvGuide();

		//Let us now play the selected TV source.
		myTv.PlayTV();

		Console.WriteLine(); //some whitespace on output for readability
	}
}

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

Image 2

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.

Image 3

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.

History

  • 04 August 2012: First Version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India

I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.

  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4

If you like my articles, please visit my website for more: www.rahulrajatsingh.com[^]

  • Microsoft MVP 2015

Comments and Discussions

 
QuestionGood Example but... Pin
Sanjay K. Gupta3-Aug-12 21:13
professionalSanjay K. Gupta3-Aug-12 21:13 
AnswerRe: Good Example but... Pin
Rahul Rajat Singh3-Aug-12 21:59
professionalRahul Rajat Singh3-Aug-12 21:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.