Bridge Pattern


The pattern allows:

  • to decouple an abstraction from its implementation so, that the two can vary independently;
  • deferring the presence of the implementation to the point where the abstraction is utilized.

Bridge Pattern


Comparing the Bridge pattern to the Strategy you can be misled by the apparent similarity. But they are meant for the different purposes. Bridge is a structural pattern and Strategy is a behavioral one. So, with the Strategy you are choosing the algorithm for the concrete operation at runtime. The Bridge pattern provides an alternative to inheritance when there is more than one version of an abstraction.

The Bridge pattern can be confused with the Adapter pattern. Though in the fact, the first pattern is just often implemented using the second one.

PHP Example

Thinking of the Bridge, the first thing which comes on mind is access to different APIs. Here is an example:


<?php
/*
 * @category Design Pattern Tutorial
 * @package Bridge Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
/**
 * Implementor
 */
interface Dao_API_Interface
{
    public function fetchProfile($guid);
}
/**
 * Concrete implementor 1
 */
class Dao_RemoteServerApi implements Dao_API_Interface
{
    public function fetchProfile($guid)
    {
        return sprintf ("Profile #%d via remote server API\n", $guid);
    }
}
/**
 * Concrete implementor 2
 */
class Dao_LocalApi implements Dao_API_Interface
{
    public function fetchProfile($guid)
    {
        return sprintf ("Profile #%d via local API\n", $guid);
    }
}
/**
 * Abstraction
 */
class Dao_User
{
    private $_api;
    public function  __construct(Dao_API_Interface $api)
    {
        $this->_api = $api;
    }
    public function fetchProfile($guid)
    {
        return $this->_api->fetchProfile($guid);
    }
}

/**
 * Usage
 */
$dao = new Dao_User(new Dao_RemoteServerApi());
print $dao->fetchProfile(1);

// Output:
// Profile #1 via remote server API

JS/ES5 Example

Here, like in the previous example, we provide the client object a bridge to the concrete API.

/*
 * @category Design Pattern Tutorial
 * @package Bridge Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
(function () {
var SessionStorageApi = (function() {
    return {
        save: function (name, value) {
            console.log('Saved in SessionStorage');
            window.sessionStorage[name] = value;
        },
        get: function (name) {
            return window.sessionStorage[name];
        }
    }
}());

var CookieApi = (function() {
    return {
        save: function (name, value) {
            console.log('Saved in Cookies');
            document.cookie = name + "=" + escape(value);
        },
        get: function (name) {
            var key, val, cookieArr = document.cookie.split(";");
            for (var i = 0; i < cookieArr.length; i++) {
                  key = cookieArr[i].substr(0, cookieArr[i].indexOf("="));
                  val = cookieArr[i].substr(cookieArr[i].indexOf("=") + 1);
                  key = key.replace(/^\s+|\s+$/g,"");
                  if (key == name) {
                    return unescape(val);
                  }
              }
        }
    }
}());

var NotepadWidget = function(api) {
    var DATA_ID = 'noteWidgetText';
    return {
        get: function() {
            return api.get(DATA_ID);
        },
        save: function(text) {
            api.save(DATA_ID, text);
        }
    }
}

/**
 * Usage
 */
var notepad = new NotepadWidget(SessionStorageApi);
notepad.save('Lorem ipsum');
console.log(notepad.get());

// Output:
// Saved in SessionStorage
// Lorem ipsum

}());