Обычно делаешь так: пришла новая фича — лезешь в существующий сервис, правишь код, потом ломаешь всё, что работало раньше. Декоратор решает это по-простому: оборачиваешь объект, добавляешь новую логику и оригинальный код не трогаешь.

В Laravel это удобно для сервисов, контроллеров и вообще любых объектов, где нужно расширение функциональности без переписывания всего проекта.

Создание декоратора

Шаг 1: Интерфейс

Создаём интерфейс, чтобы гарантировать, что декоратор и оригинальный объект совпадают по методам:

namespace App\Services;

interface ServiceInterface
{
    public function doSomething();
}

Шаг 2: Оригинальный сервис

namespace App\Services;

class OriginalService implements ServiceInterface
{
    public function doSomething()
    {
        return 'Original Service';
    }
}

Это тот код, который не трогаем. Любые изменения будут через декораторы.

Шаг 3: Декоратор

namespace App\Services;

class DecoratorService implements ServiceInterface
{
    protected $service;

    public function __construct(ServiceInterface $service)
    {
        $this->service = $service;
    }

    public function doSomething()
    {
        return $this->service->doSomething() . ' Decorated';
    }
}

Класс оборачивает оригинальный сервис и добавляет новую функциональность. Без ковыряния в исходниках.

Использование

В контроллере или другом сервисе создаём объект и оборачиваем его:

namespace App\Http\Controllers;

use App\Services\ServiceInterface;
use App\Services\OriginalService;
use App\Services\DecoratorService;

class SomeController extends Controller
{
    public function index(ServiceInterface $service)
    {
        $originalService = new OriginalService();
        $decoratedService = new DecoratorService($originalService);

        return $decoratedService->doSomething();
    }
}

Результат: Original Service Decorated. Всё. Оригинал целый, новые штуки добавляются через обертку.

Практические моменты

  • Цепочка декораторов — можно оборачивать декоратор в другой декоратор, создавая цепочку расширений.
  • Интерфейсы реально нужны — без них ты не сможешь подменить реализацию через DI или тестировать классы.
  • Контроллеры не знают о внутренностях — только интерфейс. Оригинальный сервис можно менять на мок, декоратор — на другой декоратор, и всё продолжает работать.

Почему это реально удобно

  • Расширение функциональности без ломания существующего кода.
  • Модульность: каждый декоратор делает одну вещь и не смешивает логику.
  • Тестируемость: можно мочь сервисы и декораторы отдельно.

Вывод

Декоратор в Laravel — не магия. Это простая техника, чтобы не ковырять рабочий сервис каждый раз, когда нужен новый функционал. Обернул, добавил метод или изменил поведение — оригинальный код целый, проект живой и масштабируемый.