JavaScript Design Patterns: Bridge

In my last blog post article I discussed the Singleton Design Pattern and how it is used in JavaScript. This time around the Bridge design pattern is poking its head up and asking for a bit of attention, making it the second in the JavaScript Design Patterns series.

Every place I’ve read about the Bridge pattern likes to quote the Gang of Four directly in their description of what the Bridge pattern is, so I figure why not me too? The Bridge pattern should “decouple an abstraction from its implementation so that the two can vary independently.” Bridges are quite beneficial in event-driven applications, which are quite common in JavaScript. Considering that fact, it’s surprisingly one of the most underused design patterns.

Event Listeners Example

In the following examples, I’ll be using a bit of jQuery, so if you don’t know what a function does or how it works, you can look at their documentation.

Below you’ll see a small bit of code using an API method called getXById, which is badly implemented. We are using a click event to determine which element to pull the id from. The callback itself is getXById, which gets the id from the clicked element and uses AJAX to get X from the server using the Id it found.

getXById = function() {
    var id = this.id;
	
    $.ajax({
        url:'/getx?id=' + id,
        success: function(response) {
            console.log(response);
        }
    });
}

$('someElement').bind('click', getXById);

This code isn’t all that bad if it’s only meant to be used that one specific way on the one specific page, but it’s (supposedly) part of an API, so this needs to be changed a lot. Let’s decouple getXById from the event listener and the implementation of what is done with the result:

getXById = function(id, callback) {
    $.ajax({
        url:'/getx?id=' + id,
        success: callback
    }
}

getXBridge = function() {
    var id = this.id;
    getXById(this.id, function() {
        console.log(response);
    });
}

$('someElement').bind('click', getXBridge);

Now the getXById can be used just about anywhere and you can do anything with X now.

Classical Example

What I mean by “classical” is two-fold: the example is more common to classic object-oriented programming languages and it is uses classes. Technically JavaScript doesn’t have classes but you mimic interfaces and use prototypes to mimic classes. Originally this example was in the book Head First Design Patterns, which uses Java in their example. However, this is one the minor patterns in the back of the book that didn’t actually have a code example, so I’m really just using the diagrams (except I recreated them because I’m awesome).

Our Starting Product

Original Remote Control DiagramWe start with the RemoteControl Interface. ToshibaRemote and SonyRemote both implement that interface to work with their respective televisions. With this code, you can call on(), off(), or setChannel() on any remote and even though all the TVs are different, it’ll work. What happens though, when you want to make improvements on the remotes? That’s where the Bridge pattern comes in:

Bridge Remote Control Diagram

Now, since the TVs adhere to an interface and all of the remotes adhere to another interface – actually just a class because it only needs the one implementation – we can create variations to either on through inheritance and still be compatible. Wanna see some code? I’ll show you the code for the new solution with the Bridge pattern, but I don’t think you need to see the code for the original. I really don’t think many of you need to see any code at all, but I’m sure there are those out there who’d like to see it anyway. We’re programmers, right? Show us the code!

var RemoteControl = function(tv) {
	this.tv = tv;
 
	this.on = function() {
		this.tv.on();
	};
 
	this.off = function() {
		this.tv.off();
	};
 
	this.setChannel = function(ch) {
		this.tv.tuneChannel(ch);
	};
};
 
/* Newer, Better Remote Control */
var PowerRemote = function(tv) {
	this.tv = tv;
	this.currChannel = 0;
 
	this.setChannel = function(ch) {
		this.currChannel = ch;
		this.tv.tuneChannel(ch);
	};
 
	this.nextChannel = function() {
		this.setChannel(this.currChannel + 1);
	};
 
	this.prevChannel = function() {
		this.setChannel(this.currChannel - 1);
	};
};
PowerRemote.prototype = new RemoteControl();
 
 
/** TV Interface
	Since there are no Interfaces in JavaScript I am just
	going to use comments to define what the implementors
	should implement
 
	function on
	function off
	function tuneChannel(channel)
*/
 
/* Sony TV */
var SonyTV = function() {
	this.on = function() {
		console.log('Sony TV is on');
	};
 
	this.off = function() {
		console.log('Sony TV is off');
	};
 
	this.tuneChannel = function(ch) {
		console.log('Sony TV tuned to channel ' + ch);
	};
}
 
/* Toshiba TV */
var ToshibaTV = function() {
	this.on = function() {
		console.log('Welcome to Toshiba entertainment');
	};
 
	this.off = function() {
		console.log('Goodbye Toshiba user');
	};
 
	this.tuneChannel = function(ch) {
		console.log('Channel ' + ch + ' is set on your Toshiba television');
	};
}
 
/* Let's see it in action */
var sony = new SonyTV(),
	toshiba = new ToshibaTV(),
	std_remote = new RemoteControl(sony),
	pwr_remote = new PowerRemote(toshiba);
 
std_remote.on();            // prints "Sony TV is on"
std_remote.setChannel(55);  // prints "Sony TV tuned to channel 55"
std_remote.setChannel(20);  // prints "Sony TV tuned to channel 20"
std_remote.off();           // prints "Sony TV is off"
 
pwr_remote.on();            // prints "Welcome to Toshiba entertainment"
pwr_remote.setChannel(55);  // prints "Channel 55 is set on your Toshiba television"
pwr_remote.nextChannel();   // prints "Channel 56 is set on your Toshiba television"
pwr_remote.prevChannel();   // prints "Channel 55 is set on your Toshiba television"
pwr_remote.off();           // prints "Goodbye Toshiba user"

Well, that just about wraps things up for the Bridge pattern in JavaScript. If you haven’t yet, make sure you go back and read about the Singleton Pattern. Also keep an eye out for the next article in this series: the Composite Pattern. If you thought this was helpful or you just plain liked the article, please spread the word using the social sharing buttons below the post. Thanks!

JavaScript Design Patterns series:

About the Author

Author: Joe Zim

Joe Zim

Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.


  • Apotts15

    I noticed a few errors with your example that I corrected here: http://jsfiddle.net/DzLfe/5/

    • http://www.joezimjs.com Joe Zimmerman

      Thanks for the fixes. I was up late writing that article and I had a hard time checking the code and of course I was too tired to bother testing it. However, adding those two methods wasn’t what was supposed to happen. Actually PowerRemote was supposed to inherit RemoteControl’s on and off methods. I’ll fix it up tonight and update it. Thanks for noticing and informing me.

    • http://www.joezimjs.com Joe Zimmerman

      Alright, she’s fixed up. I even decided to be smart and TEST the code. Imagine that. I guess I actually learn from my mistakes sometimes. Once again, thanks for catching that, though I can’t believe I didn’t catch a single one from that multitude of mistakes.

  • Pingback: Questions About Jquery Css – Top Apprentice Blog()

  • Exodus6777

    remote control is your abstraction, why is it being instantiated on line 81?

    • http://www.joezimjs.com Joe Zimmerman

       RemoteControl isn’t an abstraction. It’s a base class. The other remotes just make the standard remote better.

  • Mahesh Jagadeesan

    Not a critical problem, but the relationship diagram for the Bridge seems to suggest that a RemoteControl “has a” TV which doesn’t sound logical. Normally, one would expect a TV to “have” a remote, not the other way around.

  • Pingback: 10 JavaScript Design Pattern Resources - Baqar Abbas()

  • Niki

    The example with “Remote control” seems more like Decorator pattern. What is the difference?

    • http://www.joezimjs.com Joe Zimmerman

      This is definitely not the decorator pattern. The decorator pattern requires that the wrapping object have the same interface as the object that it is wrapping. That is not the case here. Here, the remotes are giving use an interface that allows us to control the TVs without using the TV’s interface. The remote allows the TV’s interface to change without us needing to change the interface that we use (the Remote). The Remote will still need to be updated, but it’s interface shouldn’t.

      In the “opposite” situation: We can alter the remotes’ interfaces in order to suit our needs without it affecting the TV.

      Decorators only add/change functionality of an object that it wraps and use the same interface as the object it wraps. In this example, we’re not changing or adding to the functionality of any of the TVs. Rather, we’re applying a different interface on top of it by wrapping it.