Adapter Pattern

The pattern allows:

  • classes with disparate interfaces to work together through an intermediate object

Adapter Pattern


See also Bridge pattern. The Adapter pattern is one of easiest to understand. Just imagine that you are on a trip through Italy and staying for a night in a hotel. You need to charge your notebook, but the Italian sockets are incompatible with your plug. So, you ought to use an intermediate device – an adapter.

PHP Example

Most of PHP frameworks implement database abstract access using the Adapter pattern. Thus, you are likely familiar with the approach and can easily follow the example:

<?php
/*
 * @category Design Pattern Tutorial
 * @package Adapter Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */

/**
 * Db Factory
 */
class Lib_Db
{
    public function  __construct(Config $config)
    {
        $className = sprintf("Lib_Db_Adapter_%s", $config->driver);
        if (class_exists($className)) {
            $db = new $className();
            $db->connect($config);
            return $db;
        }
    }
}

interface Db_Adapter_Interface
{
    public function connect(Config $config);
    public function fetch($sql);
}
/**
 * MySQLi Adapter
 */
class Lib_Db_Adapter_Mysqli implements Db_Adapter_Interface
{
    private $_mysqli;

    public function connect(Config $config)
    {
        $this->_mysqli = new mysqli($config->host, $config->user, $config->password
            , $config->dbscheme);
    }
    public function fetch($sql)
    {
        return $this->_mysqli->query($sql)->fetch_object();
    }

}
/**
 * MySQLi Pdo
 */
class Lib_Db_Adapter_Pdo implements Db_Adapter_Interface
{
    private $_dbh;

    public function connect(Config $config)
    {
        $dsn = sprintf('msqli::dbname=%s;host=%s', $config->dbscheme, $config->host);
        $this->_dbh = new PDO($dsn, $config->user, $config->password);
    }
    public function fetch($sql)
    {
        $sth = $this->_dbh->prepare($sql);
        $sth->execute();
        return $sth->fetch();
    }
}
/**
 * Usage
 */
class Config
{
    public $driver = 'Mysqli';
    public $host = 'localhost';
    public $user = 'test';
    public $password = 'test';
    public $dbscheme = 'test';
}
$config = new Config();

$db = new Lib_Db($config);
$db->fetch('SELECT * FROM `test`');

JS/ES5 Example

If you write an open-source JS library and want it to get popular, what JS framework would you use? One of the most popular? But why not many of them? You make the main logic on JS, but using helpers of framework (DOM navigation, ES5 shims). It may be not a big deal to make your own interface for those helpers and Adapters to different frameworks.

/*
 * @category Design Pattern Tutorial
 * @package Adapter Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
(function($, YUI) {

var jQuery_Adapter = function() {
    var _node;
    return {
        find : function(selector) {
            _node = $(selector);
            return this;
        },
        setAttr : function(attr, value) {
            _node.attr(attr, value);
        },
        getAttr : function(attr) {
            return _node.attr(attr);
        }
    }
}

var YUI_Adapter = function() {
    var _node;
    return {
        find : function(selector) {
            _node = Y.one(selector);
            return this;
        },
        setAttr : function(attr, value) {
            _node.set(attr, value);
        },
        getAttr : function(attr) {
            return _node.get(attr);
        }
    }
}

var Framework = (function() {
    var ADAPTER = jQuery_Adapter;
    return new ADAPTER();
}());

/**
 * Usage
 */
Framework.find('div').set('id', 'something');

}(jQuery, YUI));