Domain Centric

View Original

Understanding Gang of Four's Facade Design Pattern

TL;DR: use Facade Design Pattern to simplify usage of a complex subsystems and reduce number of dependencies your code has

During recent Design Patterns training I've attended at Inviqa (delivered by @_md) we had quite emotional discussion about differences between Facade and Adapter patterns (which are intuitively different but it was hard to understand why). This discussion led me to this blog post and I'd like to summarise our conclusions.

Intent of the Pattern according to Gang of Four:

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

As we read in above definition we may want to use this design pattern to simplify usage of some complex code by encapsulating this complexity in a Facade. We can represent it graphically as follows:

The key point here is that we have many independent Clients executing the same action and this action complexity is hidden behind Facade implementation which involves using many Subsystems.

Mailer example

Because the best way to learn for me is to learn by example I'll give an example of Facade I've ended up implementing on the project (simplified version).

In the application we had to send emails (instance of Swift Message), and content of those emails was rendered using Twig. Of course each email sent could use different template, but they were always sent using Swift Mailer. The solution we came up with looked like this:

So Templated Swift Mailer is a Facade that

  • is an instance of Templated Mailer
  • has two dependencies - Swift Mailer and Twig Environment
  • uses Swift Message to send an email

Below sample implementation:

interface TemplatedMailer
{
    public function send($email, $title, $templateName);
}

class TemplatedSwiftMailer implements TemplatedMailer
{
    private $mailer;
    private $twig;

    public function __construct(Swift_Mailer $mailer, Twig_Environment $twig)
    {
        $this->mailer = $mailer;
        $this->twig = $twig;
    }

    public function send($email, $title, $templateName)
    {
        $message = new Swift_Message($title, $this->twig->render($templateName));
        $message->setTo($email);

        $this->mailer->send($message);
    }
}

Facade vs Adapter

Now when we know how Facade looks and works we can compare it to Adapter. It's UML diagram looks like:

So even though these two patterns can look similar (in fact our Facade can be an Adapter at the same time), goals of both patterns are different:

  • Facade provides a unified interface to a set of interfaces in a subsystem,
  • Adapter converts the interface of a class into another interface clients expect.

And to give you a good example we can have an Adapter that provides interface to communicate with Database, and concrete Adaptees can provide MySQL, Oracle or other implementations.

Laravel Facades

To clarify things even more I'd like to explain as well what a Laravel Facade is and how it relates to GoF Facade.

> (Laravel)> Facades provide a "static" interface to classes that are available in the application's IoC container.

So as we read above paragraph from documentation, this kind of Facade is a completely different thing that one we discussed in this article. It provides a static way of accessing Services from Service Container. And because of that I think it's really safe to say we have a naming collision here that leads to misunderstandings between developers in PHP community.

Conclusion

On the very end I'd like to quote blog vogella.com and leave final conclusion to you:

Design Patterns have two main usages:

Common language for developers: They provide developers a common language for certain problems. For example if a developer tells another developer that he is using a Singleton, the another developer (should) know exactly what this means.


Capture good practices: Design patterns capture solutions which have been successfully applied to problems. By learning these patterns and the related problem, an unexperienced developer learns a lot about software design.