JavaScript Design Patterns: Adapter

Another post, another JavaScript design pattern. This time we’re featuring the Adapter pattern. If you’d like to view the previous posts from this series, you can check out the links at the bottom of this page. This mean, green, fighting machine can transform interfaces. Ok, it doesn’t exactly transform an interface, it really just creates a new object/function that adapts the interface of an existing object/function to match what the code knows how to use.

This may not make much sense until you get a little better context; at least that’s usually the way I feel when I’m first told how something works. So, how about we give a bit more information and context? First off, this pattern is designed to be used within existing code. Our existing code utilizes some object or function, but we want to replace it with a different one. The problem is that the new object/function uses a different interface than the one we’re currently using. Instead of changing the code in every spot that is using the current object, we bring the adapter into play.

The adapter takes the new object that we’re going to use and either wraps it, or just mediates to it, depending on how the object is used, to match it to the interface established by the old object. In the case of an object that always get instantiated with the new operator, the adapter will wrap it by containing an instance of the object within itself and passing function calls on to it. If the object is “static” in the sense that there is only one instance of it, then it will not be wrapped.

Adapter Structure

Abstract Examples

There are plenty of examples I could give to show how and when to use the Adapter. I believe the most common examples come when a project is utilizing a framework or library: jQuery for instance. The problem comes later when, for whatever reason, there is a decision to use a different library (e.g. YUI). In a large application, there is absolutely no way to go through all of the code and change every call that has to do with jQuery into YUI calls. You’d have to create an adapter, which in this case would be quite difficult, but would be better than the former idea.

Another library used in many enterprise applications is a logger. There are many different logger libraries and switching from one to another could easily come up. This might not come up much in JavaScript applications because there is a logger built into the browsers, but it’s possible.

JavaScript Coding Example

When I said it was possible, what I really meant was that it will happen right now. First let’s show the little LoggerFactory, which will allow us to more easily change the logger we’re using.

1
2
3
4
5
6
7
8
9
10
var LoggerFactory = {
getLogger: function() {
return window.console;
},
...
};
/* Example Usage */
var logger = LoggerFactory.getLogger();
logger.log("something to log");

Notice how all it does is send us the console object when we call getLogger. We’re going to pretend for the sake of this exercise that the console only has one method – log – and that it just accepts a single argument that is a string or convertible to a string; at the very least, this is the only way our JavaScript application is using the console.

Next we have another logger. This one is much more complicated because 1) it’s implemented in JavaScript, unlike the console, and 2) it send its log to the server via AJAX, which also means that it must URL encode the data (which won’t be shown here because it doesn’t have anything to do with the adapter pattern). Of course, it uses a different interface than the console too.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var AjaxLogger = {
sendLog: function() {
var data = this.urlEncode(arguments);
jQuery.ajax({
url: "http://example.com/log",
data: data
});
},
urlEncode: function(arg) {
...
return encodedData;
},
...
};

Note we’re using jQuery to accomplish the AJAX request in order to save time and hide the clutter involved with cross-browser AJAX, which has nothing to do with the adapter pattern.

Now all we need to do is create an adapter and change the factory to return the adapter instead of console.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var AjaxLoggerAdapter = {
log: function(arg) {
AjaxLogger.sendLog(arg);
}
};
/* Adjust the LoggerFactory */
var LoggerFactory = {
getLogger: function() {
// just gotta change what's returned here
return AjaxLoggerAdapter;
},
...
};

The only change we made to existing code was to one line in the factory and suddenly our entire application is now using an entirely different logger.

Complicated Adapters

This logger is a very simple example where there is only one function and that function maps pretty much straight to the old function without any difficulty. There are many instances where this isn’t the case. You may run into a problem where the functions map together very differently by using entirely different arguments, which you might have to create yourself if the old interface didn’t include them. In some cases you may just drop some of the arguments that are sent because the new object doesn’t use them at all. You never know. If it is too difficult to map the interfaces of the two objects, then you may need to try something else, which I hope doesn’t include going through thousands of lines of code to change every usage of the original object.

Concluding the JavaScript Goodness

Adapters can come in very handy and are extremely easy to implement into code if you’re using a factory to create the object that’s being replaced. Change is inevitable, especially on larger projects, so make sure to keep this one in your back pocket for the future. Below this post you’ll find the list of other posts in the JavaScript Design Patterns series (even the ones that are yet to be written). Below that is the really fun stuff: share this post with all of your friends on Facebook, Twitter, or elsewhere and if there’s anything you want to say to me or future readers, make sure to leave a comment. Help me to make this a well-known haven for anyone looking to learn about JavaScript.

JavaScript Design Patterns series:

Author: Joe Zimmerman

Author: Joe Zimmerman 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.