Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save Integralist/d67f0f913d795f703b89 to your computer and use it in GitHub Desktop.
Save Integralist/d67f0f913d795f703b89 to your computer and use it in GitHub Desktop.
Design Patterns: Adapter vs Facade vs Bridge

The three design patterns (Adapter, Facade and Bridge) all produce the result of a clean public API. The difference between the patterns are usually due to a subtle context shift (and in some cases, a behavioural requirement).

Adapter

The primary function of an Adapter is to produce a unified interface for a number of underlying and unrelated objects.

You will notice this pattern being utilised in many applications. For example, ActiveRecord (the popular Ruby ORM; object-relational mapping) creates a unified interface as part of its API but the code underneath the interface is able to communicate with many different types of databases. Allowing the consumer of the API to not have to worry about specific database implementation details.

The principle structure of this pattern is:

Current | Future
----------------
B(C)    | B(A)

The B function cannot be changed and it is dependant on the interface that was originally provided by C, but now we are passing in A which has an incompatible interface.

An adapter can solve this by creating a new function A2C which contains the relevant logic for handling the interaction between B and A.

Current | Future
----------------
B(C)    | B(A2C(A))

Facade

The primary function of a Facade is to simplify the interaction between a consumer and an interface.

Most DSL's are a facade of some form. The popular jQuery library consists of multiple facades (one for each type of feature). For example, the jQuery ajax method makes it very easy to make an XHR (XMLHttpRequest).

The difference between a Facade and an Adapter is that the Facade makes a simple abstraction, where as an Adapter will handle complex interactions by taking incoming data and constructing it to work with the underlying objects.

Bridge

The primary function of a Bridge is to decouple an abstraction from its implementation.

Adapter makes things work after they're designed
Bridge makes them work before they are

Imagine you have a function that abstracts the implementation detail of making an HTTP request to an external API endpoint. In a language like JavaScript you might tightly couple the abstraction with the consumer code.

For example:

function get(e) {
  return asyncRequest('foo?bar=' + this.id, function(response) {
    console.log(response)
  })
}

myTrigger.addEventListener('click', get, false)

The above abstraction (i.e. the get function) will only ever work within the context of a web browser. The abstraction has been tightly coupled to the consumer.

Utilising a bridge will allow us to decouple this code:

function get(id, callback) {
  return asyncRequest('foo?bar=' + id, function(response) {
    callback(response)
  })
}

function getBridge(e) {
  get(this.id, function(response) {
    console.log(response)
  })
}

myTrigger.addEventListener('click', getBridge, false)
@Integralist
Copy link
Author

Information was collated from different sources such as "Pro JS Design Patterns", rubybestpractices.com and agileevidence.com

@fedecarg
Copy link

Hi @Integralist Here's a pdf I uploaded to my google drive a while back and that you might find interesting http://goo.gl/mkx7Ne

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment