Menu
Coddy logo textTech

Padrão Observer

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 73 de 91.

O Observer Pattern é um padrão de projeto comportamental que estabelece uma relação de um-para-muitos entre objetos. Quando um objeto (o subject) muda de estado, todos os seus dependentes (os observers) são notificados e atualizados automaticamente.

Pense em uma assinatura de newsletter. A newsletter é o assunto, e os assinantes são os observadores. Quando uma nova edição é publicada, todos os assinantes a recebem automaticamente, sem que a newsletter precise conhecer os detalhes de cada assinante.

Aqui está uma implementação básica em PHP:

<?php
interface Observer {
    public function update(string $message): void;
}

class Newsletter {
    private array $subscribers = [];
    
    public function subscribe(Observer $observer): void {
        $this->subscribers[] = $observer;
    }
    
    public function publish(string $content): void {
        foreach ($this->subscribers as $subscriber) {
            $subscriber->update($content);
        }
    }
}

class EmailSubscriber implements Observer {
    public function __construct(private string $email) {}
    
    public function update(string $message): void {
        echo "Sending to {$this->email}: $message\n";
    }
}

$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");

Saída:

Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!

O padrão desacopla o assunto de seus observadores. A classe Newsletter não precisa saber se está notificando assinantes de e-mail, assinantes de SMS ou serviços de notificação push. Ela simplesmente chama update() em qualquer coisa que implemente a interface Observer. Isso torna a adição de novos tipos de observadores simples, sem a necessidade de modificar o código existente.

challenge icon

Desafio

Fácil

Vamos construir um sistema de alerta de preços de ações usando o Observer Pattern. Quando o preço de uma ação muda, todos os investidores registrados devem ser notificados automaticamente — uma aplicação perfeita deste padrão no mundo real.

Você organizará seu código em quatro arquivos:

  • Observer.php — Defina uma interface Observer com um único método update(string $stockName, float $price): void. Este é o contrato que todos os observadores devem seguir para receber notificações.
  • Investors.php — Inclua o arquivo Observer e crie duas classes que implementam a interface:
    • EmailInvestor — Recebe um endereço de e-mail em seu construtor (use promoção de construtor). Seu método update() imprime "Email to {$this->email}: {$stockName} is now \${$price}\n"
    • SmsInvestor — Recebe um número de telefone em seu construtor. Seu método update() imprime "SMS to {$this->phone}: {$stockName} is now \${$price}\n"
  • Stock.php — Inclua o arquivo Observer e crie uma classe Stock que atua como o sujeito. Sua ação deve:
    • Armazenar o nome da ação e o preço atual (use promoção de construtor para o nome, inicialize o preço como 0.0)
    • Manter um array privado de observadores
    • Ter um método subscribe(Observer $observer): void para adicionar observadores
    • Ter um método setPrice(float $price): void que atualiza o preço e notifica todos os observadores
    Ao notificar os observadores, chame o método update() de cada observador com o nome da ação e o novo preço.
  • main.php — Inclua os arquivos Investors e Stock. Você receberá três entradas: um nome de ação, um endereço de e-mail e um número de telefone.

    Crie um Stock com o nome fornecido. Inscreva um EmailInvestor com o endereço de e-mail e um SmsInvestor com o número de telefone.

    Defina o preço da ação para 150.50 para disparar as notificações para todos os assinantes.

O Observer Pattern mantém sua classe Stock desacoplada dos métodos de notificação específicos. Você poderia facilmente adicionar um PushInvestor ou SlackInvestor mais tarde sem modificar a classe Stock.

Experimente você mesmo

<?php
require_once 'Investors.php';
require_once 'Stock.php';

// Ler entradas
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));

// TODO: Criar uma Stock com o nome fornecido

// TODO: Inscrever um EmailInvestor com o endereço de e-mail

// TODO: Inscrever um SmsInvestor com o número de telefone

// TODO: Definir o preço da ação para 150.50 para disparar notificações
?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos