Design patterns: Facade
The Facade Pattern provides a simplified interface to a set of interfaces in a complex system, making the system’s functionality easier to use. It’s especially useful when you want to simplify interaction with a complex system or library.
Characteristics of the Facade Pattern
- Simplified interface: The Facade Pattern provides a simplified interface to a complex system or a set of classes, making it easier to interact with these components without having to understand their internal details.
- Isolation from the underlying system: It lets you isolate the client from the complexity of the underlying system, reducing dependencies and improving maintainability. Clients don’t need to know the specific classes and how they interact.
- Easier to use: It makes a complex system simpler and more intuitive to use, reducing the learning curve for developers and improving the user experience.
- Support for code reuse: It can bring existing classes and functionality together behind a single interface, making code reuse easier and simplifying the integration of new features.
- Easier changes: It lets you make changes to the underlying system without affecting the client. If the system is updated, the client can keep using the facade without changes.
Example in PHP:
Imagine you have a cinema management system that handles various operations such as managing movies, selling tickets and managing users. A Facade can simplify these interactions for the end user.
// Subsystem: Movie Management
class Movie {
private $title;
private $duration; // in minutes
public function __construct($title, $duration) {
$this->title = $title;
$this->duration = $duration;
}
public function getTitle() {
return $this->title;
}
public function getDuration() {
return $this->duration;
}
}
// Subsystem: Ticket Management
class Ticket {
private $movie;
private $seatNumber;
public function __construct(Movie $movie, $seatNumber) {
$this->movie = $movie;
$this->seatNumber = $seatNumber;
}
public function getDetails() {
return "Ticket for the movie '{$this->movie->getTitle()}' in seat {$this->seatNumber}.";
}
}
// Subsystem: User Management
class User {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
// Facade: Cinema System
class CinemaFacade {
private $movies = [];
private $users = [];
public function addMovie($title, $duration) {
$this->movies[] = new Movie($title, $duration);
}
public function addUser($name) {
$this->users[] = new User($name);
}
public function bookTicket($userName, $movieTitle, $seatNumber) {
// Find the user
$user = null;
foreach ($this->users as $u) {
if ($u->getName() == $userName) {
$user = $u;
break;
}
}
// Find the movie
$movie = null;
foreach ($this->movies as $m) {
if ($m->getTitle() == $movieTitle) {
$movie = $m;
break;
}
}
// If both the user and the movie exist, book the ticket
if ($user && $movie) {
$ticket = new Ticket($movie, $seatNumber);
return $ticket->getDetails();
} else {
return "Booking failed: user or movie not found.";
}
}
}
// Using the Facade
$cinema = new CinemaFacade();
$cinema->addMovie("Inception", 148);
$cinema->addMovie("The Matrix", 136);
$cinema->addUser("Alice");
$cinema->addUser("Bob");
// Booking a ticket
echo $cinema->bookTicket("Alice", "Inception", "A1") . "\n";
// Output: Ticket for the movie 'Inception' in seat A1.
echo $cinema->bookTicket("Bob", "The Matrix", "B2") . "\n";
// Output: Ticket for the movie 'The Matrix' in seat B2.
echo $cinema->bookTicket("Charlie", "Inception", "C3") . "\n";
// Output: Booking failed: user or movie not found.