Ответ
Паттерн "Адаптер" позволяет работать с несовместимыми интерфейсами, преобразуя один интерфейс класса в другой, ожидаемый клиентом. Это полезно при интеграции сторонних библиотек или устаревшего кода без изменения их исходного кода.
Пример:
interface PaymentGateway {
public function pay(float $amount): void;
}
class LegacyPaymentSystem {
public function makePayment(float $amount, string $currency): void {
echo "Paying $amount $currency via legacy systemn";
}
}
class PaymentAdapter implements PaymentGateway {
private LegacyPaymentSystem $legacySystem;
public function __construct(LegacyPaymentSystem $legacySystem) {
$this->legacySystem = $legacySystem;
}
public function pay(float $amount): void {
$this->legacySystem->makePayment($amount, 'USD');
}
}
// Клиентский код работает с PaymentGateway
$gateway = new PaymentAdapter(new LegacyPaymentSystem());
$gateway->pay(100.50);
Адаптер преобразует вызов pay() в makePayment(), скрывая различия в интерфейсах.
Ответ 18+ 🔞
А, паттерн "Адаптер"! Ну это же классика, ёпта. Представь себе ситуацию: у тебя есть новый, красивый, блестящий код, который знает, как работать только с одним типом розетки. А тут подсовывают какой-то легаси-компонент — старый, видавший виды, с разъёмами, как у древнего системного блока. И он тупо не втыкается, пизда рулю.
Вот адаптер — это как такая универсальная переходная хуйня, конвертер-переходник. Берёт этот старый, кривой интерфейс и делает из него конфетку, с которой уже может работать твой новый код. Сам легаси-класс не трогаешь, боже упаси, там черт ногу сломит. Просто оборачиваешь его в эту обёрточку, и вуаля — он начинает говорить на понятном твоему приложению языке.
Смотри, вот пример, чтобы совсем понятно было. Допустим, у тебя в проекте везде используется модный интерфейс PaymentGateway с методом pay(). Всё красиво, всё единообразно.
interface PaymentGateway {
public function pay(float $amount): void;
}
А потом бац — и тебе нужно прикрутить платежку из каменного века, LegacyPaymentSystem. И этот уродец принимает не только сумму, но ещё и валюту отдельным параметром. Совсем другой протокол, блядь.
class LegacyPaymentSystem {
public function makePayment(float $amount, string $currency): void {
echo "Paying $amount $currency via legacy systemn";
}
}
И что, переписывать под него всю систему? Да хуй там! Напрямую его использовать не получится — интерфейсы не совпадают, будет тебе ошибка на ровном месте.
Вот тут и вырубает адаптер, ядрёна вошь. Создаёшь класс-посредник, который реализует твой новый интерфейс, но внутри содержит старый объект и переводит вызовы.
class PaymentAdapter implements PaymentGateway {
private LegacyPaymentSystem $legacySystem;
public function __construct(LegacyPaymentSystem $legacySystem) {
$this->legacySystem = $legacySystem;
}
public function pay(float $amount): void {
// Вся магия здесь! Говорим старой системе то, что она хочет услышать.
$this->legacySystem->makePayment($amount, 'USD'); // Подставляем валюту по умолчанию
}
}
И теперь твой клиентский код может спокойно работать, даже не подозревая, что внутри творится какая-то алхимия. Для него это просто ещё один PaymentGateway.
// Клиенту похуй, что внутри адаптер. Он просто платит.
$gateway = new PaymentAdapter(new LegacyPaymentSystem());
$gateway->pay(100.50);
Вот и вся философия. Не ломаешь старое, не переделываешь новое. Просто делаешь прослойку, которая всех мирит. Удобно, когда подключаешь сторонние библиотеки или когда разные команды пишут модули, которые должны друг с другом общаться, а интерфейсы у них, как у инопланетян. Адаптер — и волки сыты, и овцы целы, и код не охуел от несовместимости.