Menu
Coddy logo textTech

Padrão Observer

Parte da seção Programação Orientada a Objetos do Journey de Python da Coddy. Lição 47 de 64.

O Padrão Observer cria uma relação de um para muitos, na qual um objeto (sujeito) notifica vários objetos (observadores) quando seu estado muda.

Aqui está uma classe Subject simples que gerencia observadores:

class Subject:
    def __init__(self):
        self._observers = []
    
    def add_observer(self, observer):
        self._observers.append(observer)
    
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

O sujeito mantém uma lista de observadores e pode notificar todos de uma vez.

Crie classes observadoras simples:

class EmailNotifier:
    def update(self, message):
        print(f"Email sent: {message}")

class SMSNotifier:
    def update(self, message):
        print(f"SMS sent: {message}")

Cada observador tem um método update que é chamado quando é notificado.

Use o padrão observer:

# Criar subject
news = Subject()

# Criar observers
email = EmailNotifier()
sms = SMSNotifier()

# Adicionar observers ao subject
news.add_observer(email)
news.add_observer(sms)

# Notificar todos os observers
news.notify("Breaking news: Python is awesome!")

Crie um exemplo prático com um rastreador de preços de ações:

class Stock:
    def __init__(self, symbol, price):
        self.symbol = symbol
        self._price = price
        self._observers = []
    
    def add_observer(self, observer):
        self._observers.append(observer)
    
    def set_price(self, price):
        self._price = price
        self.notify()
    
    def notify(self):
        for observer in self._observers:
            observer.update(self.symbol, self._price)

class Investor:
    def __init__(self, name):
        self.name = name
    
    def update(self, symbol, price):
        print(f"{self.name} notified: {symbol} is now ${price}")

# Use o rastreador de ações
apple_stock = Stock("AAPL", 150)

investor1 = Investor("Alice")
investor2 = Investor("Bob")

apple_stock.add_observer(investor1)
apple_stock.add_observer(investor2)

apple_stock.set_price(155)  # Notifica todos os investidores

Saída:

Email sent: Breaking news: Python is awesome!
SMS sent: Breaking news: Python is awesome!
Alice notified: AAPL is now $155
Bob notified: AAPL is now $155

Ponto principal: o Padrão Observer permite que um objeto notifique automaticamente vários outros quando algo muda. O sujeito mantém uma lista de observadores e chama o método update deles quando necessário. Isso é útil para notificações, sistemas de eventos e para manter várias partes da sua aplicação sincronizadas.

challenge icon

Desafio

Médio

Implemente o Padrão Observer criando um sistema de monitoramento meteorológico. Você precisa criar duas classes nas áreas designadas do código.

Etapa 1: Crie a classe WeatherStation

Escreva sua classe WeatherStation onde o comentário indicar. Essa classe deve:

  • Herdar da classe Subject (use class WeatherStation(Subject):)
  • Inicializar com:
    • Chamar o construtor da classe pai usando super().__init__()
    • Definir a temperatura inicial como 0 usando um atributo com um único sublinhado self._temperature (a convenção do Python para um atributo interno)
  • Implementar <strong>set_temperature(self, temperature)</strong>:
    • Atualizar o atributo de temperatura interno
    • Chamar self.notify(self._temperature) para notificar todos os observadores
  • Implementar <strong>get_temperature(self)</strong>:
    • Retornar o valor atual da temperatura

Etapa 2: Crie a classe WeatherDisplay

Escreva sua classe WeatherDisplay onde o comentário indicar. Essa classe deve:

  • Herdar da classe Observer (use class WeatherDisplay(Observer):)
  • Inicializar com:
    • Aceitar um parâmetro name
    • Armazenar o nome como self.name
  • Implementar <strong>update(self, temperature)</strong>:
    • Exibir a mensagem de atualização da temperatura exatamente no formato mostrado abaixo

Formato da mensagem:

Quando um display recebe uma atualização de temperatura, ele deve exibir exatamente:

Display [name]: Current temperature is [temperature]C

Exemplo de uso:

# Criar estação meteorológica e displays
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")

# Anexar displays à estação
station.attach(phone_display)
station.attach(tablet_display)

# Atualizar temperatura - ambos os displays serão notificados
station.set_temperature(25.5)

# Saída:
# Display Phone: Current temperature is 25.5C
# Display Tablet: Current temperature is 25.5C

Observações importantes:

  • Os métodos attach() e detach() já estão implementados na classe base Subject — você não precisa implementá-los nem chamá-los na sua classe WeatherStation
  • No exemplo de uso acima, station.attach(phone_display) é chamado pelo usuário da sua classe, não dentro da implementação de WeatherStation
  • Sua WeatherStation só precisa chamar self.notify() quando a temperatura mudar — a classe base Subject cuida do restante
  • Concentre-se em implementar os três métodos necessários em WeatherStation e os dois métodos necessários em WeatherDisplay, conforme especificado acima

Experimente você mesmo

class Subject:
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        self._observers.append(observer)
        
    def detach(self, observer):
        self._observers.remove(observer)
        
    def notify(self, data):
        for observer in self._observers:
            observer.update(data)
            
class Observer:
    def update(self, data):
        pass

# Escreva sua classe WeatherStation aqui

# Escreva sua classe WeatherDisplay aqui

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

Pratique por conta própria: Compilador de Python online