The primary goal of the Delegate design pattern is to delegate tasks to one or more other objects. This is highly useful when you need to abstract out logic to a higher level, as it helps you avoid lots of difficult-to-maintain nested if statements and fits nicely with encapsulation’s ”Don’t Ask, Tell” methodology.

The Pattern
class Worker
{
    public function liftBox() { echo "lifted a box."; }
}

class Delegator
{
    private $worker;
    public function __construct()
    {
        $this->worker = new Worker;
    }

    public function liftBox()
    {
        return $this->worker->liftBox();
    }
}

Delegator did nothing itself and instead told Worker what to do and passed on its results with little or no modification.

Real World Example

With Rosetta Blog, I quickly discovered that Drupal 6 uses a dramatically different database schema for articles. Since I want to support both (and drupal 7, wordpress, etc.) I knew I’d have to abstract out the logic.

A new developer would have done something like this:

// ArticleController
if ($config['blogPlatform'] = 'Drupal5')
{
    $articleManager = new Drupal5ArticleManager;
}
else if ($config['blogPlatform'] = 'Drupal6')
{
    $articleManager = new Drupal6ArticleManager;
}
    
$article = $articleManager->getMessageByID($id);

But this breaks the laws of encapsulation, because the Controller aspect of MVC has to know way too much about the Article model (e.g. that Drupal5 and 6 are supported…)

A better system is to use the delegate system:

interface ArticleManagerI
{
    public function fetchArticleByName($articleName);
    public function fetchArticleByID($articleID);
    public function fetchArticleSummaries($articleLimit, $offset = 0);
}

class ArticleManager implements ArticleManagerI
{
    /** @var ArticleManagerI **/
    private $articleManager;

    public function __construct($blogPlatform)
    {
        $className = $blogPlatform . 'ArticleManager';
        $this->articleManager = new $className();
    }

    public function fetchArticleByID($articleID)
    {
        return $this->articleManager->fetchArticleByID($articleID);
    }
}

It may not look like much but now the controller doesn’t have to give a damn about what platforms your blog supports.

$article = new ArticleManager($config['blogPlatform']);