Facade introduces a new interface for the client to interface with the underlying complex subsystem classes. This is a high-level interface that hides the subsystems from the clients.
Facade uses the objects and method from the already existing class(subsystem) objects. It is the responsibility of the facade, to provide the desired functionality to the client, with simplicity.
This article is about the Facade pattern implementation in PHP. Check the implementation details and examples.
Implementation
Follow the steps below to implement Facade pattern in PHP-
- Create a facade class.
- Define private property for each of the subsystem classes and initialize those properties with new objects in the facade constructor.
- In the method implementations, call the methods from the subsystem objects whenever needed. Add additional steps of code if required.
- In the client use the create a facade class object and use that object.
Here is a simple example of Facade implementation-
<?php
// Facade pattern in PHP
// First subsystem
class Subsystem1 {
public function operation1(): void {
echo "Subsystem 1: operation 1n";
}
public function operation2(): void {
echo "Subsystem 1: operation 2n";
}
}
// Second subsystem
class Subsystem2 {
public function operation3(): void {
echo "Subsystem 2: operation 3n";
}
public function operation4(): void {
echo "Subsystem 2: operation 4n";
}
}
// Third subsystem
class Subsystem3 {
public function operation5(): void {
echo "Subsystem 3: operation 5n";
}
}
// Facade
class Facade {
private Subsystem1 $subsystem1;
private Subsystem2 $subsystem2;
private Subsystem3 $subsystem3;
public function __construct() {
// Initialize subsystems
$this->subsystem1 = new Subsystem1();
$this->subsystem2 = new Subsystem2();
$this->subsystem3 = new Subsystem3();
}
public function exampleOp1(): void {
// Use operation from subsystem as required
$this->subsystem1->operation1();
$this->subsystem2->operation3();
}
public function exampleOp2(): void {
// Use operation from subsystem as required
$this->subsystem1->operation2();
$this->subsystem3->operation5();
}
}
// Demo
$facade = new Facade();
$facade->exampleOp1();
$facade->exampleOp2();
Output of the above code will be –
Subsystem 1: operation 1
Subsystem 2: operation 3
Subsystem 1: operation 2
Subsystem 3: operation 5
Examples
Here are a few examples of Facade pattern in PHP-
Example #1: Travel Plan
We have some classes for travel related operation- Car, Direction, Toll, Weather etc. We want to implement a facade for making it simpler to use all those subsystem classes.
Car Class [subsystem class]
- Create file “Car.php”.
- Define class “Car” and implement required methods.
<?php
// Car.php
namespace BigBoxCodeDesignPatternFacadeTravelPlan;
class Car {
public function startEngine(): void {
echo "Start Enginen";
}
public function stopEngine(): void {
echo "Stop Enginen";
}
public function goStraight(): void {
echo "Go Straight: ↑n";
}
public function goLeft(): void {
echo "Go Left: ←n";
}
public function goRight(): void {
echo "Go Right: →n";
}
public function getDistanceTravelled(): float {
// This is some random calculation for demo purpose
return ((rand(0, 180) * ((10000 - 100) * 10 + 1)) + 100 * 10) / 10.0;
}
}
Direction Class [subsystem class]
- Create file “Direction.php”.
- Define class “Direction”.
- Define methods as per requirement.
<?php
// Direction.php
namespace BigBoxCodeDesignPatternFacadeTravelPlan;
use BigBoxCodeDesignPatternFacadeTravelPlanPoint;
class Direction {
public function __construct(
private float $startLat,
private float $startLng,
private float $endLat,
private float $endLng
) {
}
public function getLocationDetails(float $lat, float $lng) {
echo "Country: ABCn";
echo "City: DEFn";
echo "State: GHIn";
echo "Zip: 101010n";
}
public function getCurrentLocation(): Point {
// This is some random calculation for demo purpose
$currentLat = rand(0, 180);
$currentLng = rand(0, 180);
return new Point($currentLat, $currentLng);
}
public function getNextMove(): string {
// This is some random calculation for demo purpose
$nextMoves = ["straight", "left", "right"];
return $nextMoves[rand(0, 2)];
}
public function getFullRoute(): array {
$points = [];
for ($i = 0; $i < 10; $i++) {
// This is some random calculation for demo purpose
$currentLat = (rand(0, 180) * ((90 - (-90) * 10 + 1) - 90 * 10)) / 10.0;
$currentLng = (rand(0, 180) * ((180 - (-180) * 10 + 1) - 180 * 10)) / 10.0;
$points[$i] = new Point($currentLat, $currentLng);
}
return $points;
}
}
Toll Class [subsystem class]
- Create file “Toll.php”.
- Define class “Toll”.
<?php
// Toll.php
namespace BigBoxCodeDesignPatternFacadeTravelPlan;
use BigBoxCodeDesignPatternFacadeTravelPlanPoint;
class Toll {
public function getTollPoints(float $lat, float $lng): array {
$points = [];
for ($i = 0; $i < 10; $i++) {
// This is some random calculation for demo purpose
$currentLat = rand(0, 180);
$currentLng = rand(0, 180);
$points[$i] = new Point($currentLat, $currentLng);
}
return $points;
}
public function getTollAmount(float $tollPointId): float {
// This is some random calculation for demo purpose
return rand(0, 100);
}
public function getTotalToll(float $lat, float $lng): float {
// This is some random calculation for demo purpose
return rand(0, 100);
}
}
Weather Class [subsystem class]
- Create file “Weather.php”.
- Create class “Weather”.
<?php
// Weather.php
namespace BigBoxCodeDesignPatternFacadeTravelPlan;
class Weather {
public function getWeatherInfo(float $lat, float $lng): void {
echo "Temperature: 20.7n";
echo "Precipitation: 1%n";
echo "Humidity: 73%n";
echo "Wind: 8 km/hn";
}
}
Facade Class
- Create file “TravelFacade.php”.
- Create class “TravelFacade”.
- Declare private properties for objects of type “Car”, “Toll”, “Weather”, and “Direction”. In the constructor initialize the properties and assign an object of relevant class.
- Define methods and use the methods from the objects of the subsystems (Car, Toll, Weather, Direction).
<?php
// TravelFacade.php
namespace BigBoxCodeDesignPatternFacadeTravelPlan;
class TravelFacade {
private float $startLat;
private float $startLng;
private float $endLat;
private float $endLng;
private Direction $direction;
private Toll $toll;
private Car $car;
private Weather $weather;
// define constructor
public function __construct(float $startLat, float $startLng, float $endLat, float $endLng) {
$this->startLat = $startLat;
$this->startLng = $startLng;
$this->endLat = $endLat;
$this->endLng = $endLng;
// Initialize classes
$this->direction = new Direction($startLat, $startLng, $endLat, $endLng);
$this->car = new Car();
$this->toll = new Toll();
$this->weather = new Weather();
}
public function getRoute(): array {
return $this->direction->getFullRoute();
}
public function getLocationInfo(float $lat, float $lng): void {
$this->direction->getLocationDetails($lat, $lng);
$this->weather->getWeatherInfo($lat, $lng);
}
public function getCurrentLocation(): Point {
return $this->direction->getCurrentLocation();
}
public function operateCar(): void {
$fullRoute = $this->direction->getFullRoute();
$this->car->startEngine();
foreach ($fullRoute as $point) {
$nextMove = $this->direction->getNextMove();
switch ($nextMove) {
case "straight":
$this->car->goStraight();
break;
case "left":
$this->car->goLeft();
break;
case "right":
$this->car->goRight();
break;
}
}
$this->car->stopEngine();
}
public function getTotalTollAmount(float $lat, float $lng) {
echo "Total Toll Amount: " . $this->toll->getTotalToll($lat, $lng) . "n";
}
}
Demo
We just need to create a facade object and call the methods from the object.
<?php
// demo.php
require __DIR__ . '/../../vendor/autoload.php';
use BigBoxCodeDesignPatternFacadeTravelPlanTravelFacade;
$travelFacade = new TravelFacade(10, 10, 20, 30);
$currentLocation = $travelFacade->getCurrentLocation();
echo "Current Latitude: " . $currentLocation->getLat() . "n";
echo "Current Longitude: " . $currentLocation->getLng() . "n";
$travelFacade->getLocationInfo(20, 30);
$travelFacade->getTotalTollAmount(20, 30);
$travelFacade->operateCar();
Output
Output of the above demo code will be as below. Output may differ for you as most of the methods here use dummy(with random) code.
Current Latitude: 37
Current Longitude: 129
Country: ABC
City: DEF
State: GHI
Zip: 101010
Temperature: 20.7
Precipitation: 1%
Humidity: 73%
Wind: 8 km/h
Total Toll Amount: 56
Start Engine
Go Left: ←
Go Right: →
Go Right: →
Go Left: ←
Go Straight: ↑
Go Right: →
Go Right: →
Go Straight: ↑
Go Straight: ↑
Go Right: →
Stop Engine
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Travel Plan | GitHub |
Other Code Implementations
Use the following links to check Facade pattern implementation in other programming languages.