Photo by Radowan Nakif Rehan on Unsplash
Design Patterns: Facade Pattern
Get real with the Facade design pattern
The Facade pattern is a structural design pattern that provides a simplified interface to a complex system or set of subsystems. This pattern is suitable for projects where there is a need to simplify and abstract the interactions between different components or systems and to provide a unified and consistent interface to clients.
One example of a project where the Facade pattern is useful is in the development of an e-commerce website that integrates multiple third-party services, such as payment gateways, shipping providers, and inventory management systems. By using the Facade pattern, a simplified interface can be created that abstracts the complexities of the different systems and provides a unified and consistent interface to clients. This can help to improve the usability and reliability of the e-commerce website and make it easier to maintain and update the integrations over time.
Another example of a project where the Facade pattern is useful is in the development of a scientific simulation that uses multiple libraries or frameworks, such as numerical methods, data visualization, or machine learning. By using the Facade pattern, a simplified interface can be created that abstracts the complexities of the different libraries and provides a unified and consistent interface to researchers or analysts. This can help to improve the accessibility and reproducibility of the scientific simulation and make it easier to modify or extend the functionality over time.
In general, the Facade pattern should be used in projects where there is a need to simplify and abstract the interactions between different components or systems and to provide a unified and consistent interface to clients. It can help to improve the modularity and maintainability of the code, by reducing the coupling between the components and making it easier to add or modify functionality over time.
Let's get our hands dirty and take a look at a practical example.
class MediaFacade {
constructor() {
this.mediaPlayer = new MediaPlayer();
this.playlist = new Playlist();
}
play() {
this.mediaPlayer.play();
}
pause() {
this.mediaPlayer.pause();
}
stop() {
this.mediaPlayer.stop();
}
next() {
this.playlist.next();
this.mediaPlayer.play(this.playlist.getCurrent());
}
prev() {
this.playlist.prev();
this.mediaPlayer.play(this.playlist.getCurrent());
}
setVolume(volume) {
this.mediaPlayer.setVolume(volume);
}
loadPlaylist(playlist) {
this.playlist.load(playlist);
this.mediaPlayer.play(this.playlist.getCurrent());
}
}
class MediaPlayer {
constructor() {
this.volume = 50;
}
play(media) {
console.log(`Playing ${media}`);
}
pause() {
console.log('Paused');
}
stop() {
console.log('Stopped');
}
setVolume(volume) {
this.volume = volume;
console.log(`Volume set to ${volume}`);
}
}
class Playlist {
constructor() {
this.playlist = [];
this.currentIndex = -1;
}
load(playlist) {
this.playlist = playlist;
this.currentIndex = 0;
}
getCurrent() {
return this.playlist[this.currentIndex];
}
next() {
if (this.currentIndex < this.playlist.length - 1) {
this.currentIndex++;
} else {
this.currentIndex = 0;
}
}
prev() {
if (this.currentIndex > 0) {
this.currentIndex--;
} else {
this.currentIndex = this.playlist.length - 1;
}
}
}
// usage example
const mediaFacade = new MediaFacade();
mediaFacade.loadPlaylist(['song1.mp3', 'song2.mp3', 'song3.mp3']);
mediaFacade.play();
mediaFacade.next();
mediaFacade.setVolume(70);
In this example, we define a MediaFacade
class that serves as a simplified interface to the complex functionalities of the media player. The MediaFacade
class wraps a MediaPlayer
instance and a Playlist
instance, and exposes only the methods that are needed to interact with the media player, such as play
, pause
, stop
, next
, prev
, and setVolume
.
The MediaPlayer
class and the Playlist
class are the subsystems that perform the actual functionalities of playing media and managing playlists. The MediaFacade
class provides a simplified way for clients to interact with these subsystems without having to understand their complexities.
In the usage example, we create an instance of MediaFacade
, load a playlist, play the media, switch to the next media, and set the volume. This example demonstrates how the Facade pattern can simplify the interface of a media player app and provide a simpler way for clients to interact with it.