Imagine now that we are building a music player, and recently, market demands have grown. Now, users expect support not just for MP3 and WAV but also for FLAC files within our music player system. This development poses a unique challenge: How do we extend our music player's capabilities to embrace this new format without altering its established interface?
Let's say that we currently have a MusicPlayer class that can only play MP3 files:
<?php
class MusicPlayer
{
public function play($file)
{
if (substr($file, -4) === '.mp3') {
echo "Playing " . $file . " as mp3.\n";
} else {
echo "File format not supported.\n";
}
}
}
Let's approach this challenge by introducing an adapter that encapsulates different formats and extensions modularly and maintainably:
<?php
class MusicPlayerAdapter
{
private $player;
private $formatAdapters;
public function __construct(MusicPlayer $player)
{
$this->player = $player;
$this->formatAdapters = [
'.wav' => function($file) {
$convertedFile = str_replace('.wav', '.mp3', $file);
echo "Converting $file to $convertedFile and playing as mp3...\n";
$this->player->play($convertedFile);
},
'.flac' => function($file) {
$convertedFile = str_replace('.flac', '.mp3', $file);
echo "Converting $file to $convertedFile and playing as mp3...\n";
$this->player->play($convertedFile);
}
];
}
public function play($file)
{
$fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
$fileExtension = '.' . $fileExtension;
if (isset($this->formatAdapters[$fileExtension])) {
$this->formatAdapters[$fileExtension]($file);
} else {
$this->player->play($file);
}
}
}
// Upgraded music player with enhanced functionality through the composite adapter
$legacyPlayer = new MusicPlayer();
$enhancedPlayer = new MusicPlayerAdapter($legacyPlayer);
$enhancedPlayer->play("song.mp3"); // Supported directly
$enhancedPlayer->play("song.wav"); // Supported through adaptation
$enhancedPlayer->play("song.flac"); // Newly supported through additional adaptation
This adaptation ensures that we can extend the MusicPlayer to include support for additional file formats without altering its original code. The MusicPlayerAdapter acts as a unified interface to the legacy MusicPlayer, handling formats by determining the appropriate strategy based on the file type.