Sobes.tech
Middle

Como funciona um decorador em PHP?

sobes.tech IA

Resposta da IA

O padrão "Decorador" adiciona dinamicamente um novo comportamento a um objeto existente envolvendo-o em outro objeto, chamado decorador.

  • Componentes:

    • Interface (Component): Declara métodos comuns para o objeto original e seus decoradores.
    • Componente Concreto (Concrete Component): Objeto principal que se deseja decorar.
    • Decorador Base (Decorator): Classe abstrata ou interface que contém uma referência a um objeto da interface (Component) e implementa seus métodos, geralmente delegando a chamada a esse objeto.
    • Decoradores Concretos (Concrete Decorators): Implementam novas funcionalidades, complementando ou modificando o comportamento do componente base.
  • Princípio de funcionamento:

    • O decorador contém uma referência ao objeto que decora (composição).
    • O decorador tem a mesma interface que o objeto decorado.
    • Ao chamar um método no decorador, este realiza lógica adicional antes ou depois de chamar o método correspondente no objeto decorado, ou o substitui completamente (embora isso não seja uma utilização típica).
  • Vantagens:

    • Permite adicionar funcionalidades aos objetos em tempo de execução, e não de forma estática por herança.
    • Evita a "explosão" da hierarquia de classes ao combinar múltiplos comportamentos diferentes.
    • Permite criar combinações de comportamentos flexíveis.
  • Exemplo:

<?php

// Interface do componente
interface Coffee {
    public function getCost(): float;
    public function getDescription(): string;
}

// Componente concreto
class SimpleCoffee implements Coffee {
    public function getCost(): float {
        return 5.0;
    }

    public function getDescription(): string {
        return "Café simples";
    }
}

// Decorador base
abstract class CoffeeDecorator implements Coffee {
    protected Coffee $coffee;

    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function getCost(): float {
        return $this->coffee->getCost();
    }

    public function getDescription(): string {
        return $this->coffee->getDescription();
    }
}

// Decorador concreto: Adicionar leite
class MilkDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 2.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", com leite";
    }
}

// Decorador concreto: Adicionar açúcar
class SugarDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 1.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", com açúcar";
    }
}

// Uso:
// Criar um café simples
$coffee = new SimpleCoffee();
echo $coffee->getDescription() . " - " . $coffee->getCost() . "\n"; // Café simples - 5

// Adicionar leite
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->getDescription() . " - " . $coffeeWithMilk->getCost() . "\n"; // Café simples, com leite - 7

// Adicionar açúcar
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->getDescription() . " - " . $coffeeWithMilkAndSugar->getCost() . "\n"; // Café simples, com leite, com açúcar - 8