Что это такое
Паттерн Адаптер заставляет класс с неподходящим интерфейсом соответствовать интерфейсу, который ожидает ваш код, — как дорожный переходник между зарубежной розеткой и вашим зарядным устройством.
Старый класс изменить нельзя (он приходит из библиотеки или от него зависит другой код). Поэтому вы оборачиваете его в небольшой класс, который реализует нужный вам интерфейс и транслирует вызовы.
Пример: старый принтер в роли логгера
Нашему коду нужен Logger с методом log($message). Устаревший класс предлагает только writeLine($prefix, $text). Адаптер держит внутри старый класс и транслирует один вызов в другой.
Адаптер транслирует вызов
run() работает с любым Logger; адаптер делает устаревший принтер одним из них, не затрагивая его код.
Вывод: PHP-скрипт
<?php
// Интерфейс, который ожидает наш код.
interface Logger {
public function log(string $message): void;
}
// Старый класс из библиотеки с другим методом — изменить его мы не можем.
class LegacyPrinter {
public function writeLine(string $prefix, string $text): void {
echo $prefix . " | " . $text, "\n";
}
}
// Адаптер подгоняет старый класс под новый интерфейс.
class PrinterAdapter implements Logger {
public function __construct(private LegacyPrinter $legacy) {}
public function log(string $message): void {
$this->legacy->writeLine("LOG", $message);
}
}
function run(Logger $l): void {
$l->log("сервис запущен");
$l->log("запрос обработан");
}
run(new PrinterAdapter(new LegacyPrinter()));
Когда его применять
Применяйте, когда работающий код и нужный интерфейс не совпадают, а изменить ни одну из сторон вы не можете (или не должны) — сторонние библиотеки, устаревший код, сгенерированный код.
Не применяйте, когда обе стороны принадлежат вам — тогда просто измените одну из них так, чтобы они совпали. Адаптер между двумя классами, которыми вы управляете, — это обходной путь вместо решения, которое можно просто принять.
Плюсы и минусы
Плюсы: старый и новый код работают вместе без изменений с обеих сторон; трансляция живёт в одном небольшом классе, который легко протестировать.
Минусы: при чтении появляется ещё один переход; множество адаптеров, наложенных друг на друга, — признак того, что переработки требуют сами интерфейсы.