НЕ МОЛЧИ!!!    Сделай что-нибудь, чтобы остановить войну России в Украине.
...бойтесь людей равнодушных - именно с их молчаливого согласия происходят все самые ужасные преступления на свете.   ("Репортаж с петлёй на шее")

Шаблон проектирования Adapter (Адаптер)

Описывается шаблон проектирования Адаптер или Adapter, приводится описание шаблона и пример его реализации.

Наименование шаблона прямо говорит о назначении — обеспечить взаимодействие объектов с несовместимыми интерфейсами. Если оперировать общепринятыми терминами, то исходные данные следующие. Имеется некий клиент или приложение с устоявшимся интерфейсом взаимодействия и есть некоторый сервис, который реализует то, что нужно клиенту. Проблема в том, что интерфейс этого сервиса несовместим с нашим клиентом. Можно, конечно, реализовать требуемый сервис с нужным интерфейсом, но часто проще адаптировать существующий сервис к интерфейсу клиента.

Осуществляется это за счет создания обертки над сторонним сервисом и приведением его интерфейса или данных к нужному виду. Если детальнее, адаптер принимает запросы от клиента через клиентский интерфейс и направляет их сервису по интерфейсу, который тот понимает. Полученный ответ сервиса приводится к требованиям клиента и отправляется последнему.  Как видите, все достаточно просто.
Замечу, что существует два вида адаптеров: адаптер классов и адаптер объектов, в чем разница, надеюсь, понятно. Тут можно добавить, что, как правило, адаптер объектов содержит в себе ссылку на объект стороннего сервиса, при реализации адаптера классов наследуются интерфейсы как клиента, так и сервиса, поэтому потребности в ссылке на сервис зачастую нет.   Надеюсь, реализация этого шаблона ясна из описанного выше и весьма сильно зависит от конкретной ситуации. Тем не менее приведу пример.

//интерфейс клиента
interface IVehicle
{
    function drive();
}

/*
Для наглядности приводится 2 класса, реализующие интерфейс некоего приложения
*/
// сервис1, реализующий интерфейс
class Car implements IVehicle
{
    public drive() {
       return "Drive by car";
    }
}

// сервис2, реализующийй интерфейс
class Bus implements IVehicle
{
    public drive() {
       return "Drive by bus"; 
    }
}


// сервис3 с другим интерфейсом, но который нужен приложению
class Bicycle
{
    public move() {
       return ("A ride on the bicycle");
    }
}

// класс адаптера, преобразующий сторонний интерфейс к интерфейсу клиента
class DriveAdapter implements IVehicle
{
    private $bicycle;

    public _construct(Bicycle $bicycle)
    {
        $this->bicycle = $bicycle;
    }
 
    public drive()
    {
        return $this->bicycle->move();
    }
}

Ниже приведен фрагмент простенького кода, отображающего работу шаблона проектирования Адаптер.

<?php

require 'IVehicle.php';
require 'Car.php';
require 'Bus.php';
require 'Bicycle.php';
require 'BicycleAdapter.php';

//функция, запрашивающая информацию у определенного сервиса
function getInfo(IVehicle $vehicle) {
  echo '<br>' .$vehicle->drive();
}

$car = new Car();
$bus = new Bus();
$adapter = new BicycleAdapter(new Bicycle());
echo '<br><b>Отклик сервиса приложения</b>';
getInfo($car);
getInfo($bus);
echo '<br>============<br>';
echo '<b>Отклик стороннего сервиса</b>';
getInfo($adapter);
echo '<br>============<br>';
?>
</body>
</html>

В итоге работы тестового кода будет следующий вывод.

Отклик сервиса приложения
I drive by car
I drive by bus
============
Отклик стороннего сервиса
A ride on the bicycle
============

Перейти к списку шаблонов проектирования.