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.

Folha de consulta

O Padrão Observer estabelece uma relação de um-para-muitos onde um sujeito notifica automaticamente todos os observadores quando seu estado muda.

Componentes Chave:

  • Interface Observer — Define o contrato para observadores com um método update()
  • Sujeito (Subject) — Mantém uma lista de observadores e os notifica sobre mudanças de estado
  • Observadores Concretos — Implementam a interface Observer para receber notificações

Implementação Básica:

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

class Subject {
    private array $observers = [];
    
    public function subscribe(Observer $observer): void {
        $this->observers[] = $observer;
    }
    
    public function notify(string $data): void {
        foreach ($this->observers as $observer) {
            $observer->update($data);
        }
    }
}

class ConcreteObserver implements Observer {
    public function __construct(private string $name) {}
    
    public function update(string $message): void {
        echo "Notifying {$this->name}: $message\n";
    }
}

$subject = new Subject();
$subject->subscribe(new ConcreteObserver("Observer1"));
$subject->subscribe(new ConcreteObserver("Observer2"));
$subject->notify("State changed!");

Benefícios:

  • Desacopla o sujeito de seus observadores
  • Fácil de adicionar novos tipos de observadores sem modificar o código existente
  • Suporta inscrição/cancelamento de inscrição dinâmica

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