Facade is used to simplify the use of an existing complex interfaces. It decouples a client from a sub-system so the client interacts with facade instead of the sub-system. It especially comes handy when dealing with a legacy code, a third party code, a complex code or a hard to refactor/test code. So in short terms, a facade turns something ugly into something nice.


A good facade would have a constructor with interface-type-hinted parameters and wouldn't have a new keyword.


How do implement it


  1. Create a class which will be the facade.

  2. Pass the original classes as interface-type-hinted parameter to the facade's constructor.

  3. Create methods which make use of the original class' methods.

How it works


  1. Client request something.

  2. Request goes to facade.

  3. Facade talks to relevant sub-system to do the job.

  4. Sub-system responses back to facade after completing the work - (optional).

  5. Facade responses back to client - (optional).

Example


interface ShareInterface
{
public function setMessage($message);
public function share();
}

class Twitter implements ShareInterface
{
private $message;

public function setMessage($message)
{
$this->message = $message;
}

public function share()
{
echo sprintf('Sharing "%s" on Twitter.', $this->message).PHP_EOL;
}
}

class Facebook implements ShareInterface
{
private $message;

public function setMessage($message)
{
$this->message = $message;
}

public function share()
{
echo sprintf('Sharing "%s" on Facebook.', $this->message).PHP_EOL;
}
}

class Linkedin implements ShareInterface
{
private $message;

public function setMessage($message)
{
$this->message = $message;
}

public function share()
{
echo sprintf('Sharing "%s" on Linkedin.', $this->message).PHP_EOL;
}
}

$twitter = new Twitter();
$twitter->setMessage('Learning Facade pattern.');
$twitter->share();

$facebook = new Facebook();
$facebook->setMessage('Learning Facade pattern.');
$facebook->share();

$linkedin = new Linkedin();
$linkedin->setMessage('Learning Facade pattern.');
$linkedin->share();

As you can see above, in order to share a message on three different social media channels, we ended up repeating same steps three times. It would be even more painful if we had more social media channels to share the message. What would be an ideal scenario is, sharing the message on all social media channels in one go. To do that, we can introduce a Facade class as seen below.


class SocialMedia
{
private $twitter;
private $facebook;
private $linkedin;

public function __construct(ShareInterface $twitter, ShareInterface $facebook, ShareInterface $linkedin)
{
$this->twitter = $twitter;
$this->facebook = $facebook;
$this->linkedin = $linkedin;
}

public function setMessage($message)
{
$this->twitter->setMessage($message);
$this->facebook->setMessage($message);
$this->linkedin->setMessage($message);

return $this;
}

public function share()
{
$this->twitter->share();
$this->facebook->share();
$this->linkedin->share();
}
}

$socialMedia = new SocialMedia(new Twitter(), new Facebook(), new Linkedin());
$socialMedia->setMessage('Learning Facade pattern.')->share();

As you can see above, we set the message once and share it on all three social media channels in one go.