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 investidoresSaí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 $155Ponto 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.
Desafio
MédioImplemente 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)
- Chamar o construtor da classe pai usando
- 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
- Aceitar um parâmetro
- 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]CExemplo 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.5CObservações importantes:
- Os métodos
attach()edetach()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
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
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosO Parâmetro selfMétodosAtributosMétodo Construtor (__init__)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Função super()Sobrescrita de MétodoHerança MúltiplaOrdem de Resolução de MétodosRecapitulação - Hierarquia de Funcionários7Métodos Especiais
Introdução aos Métodos MágicosSobrecarga de OperadoresMétodos Mágicos de ContêinerRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução a Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy2Decoradores
Introdução aos DecoradoresDecorador de PropriedadeDecorador de Método EstáticoDecorador de Método de Classe5Polimorfismo
Sobrescrita de Método RevisitadaDuck TypingClasses e Métodos AbstratosDesign de InterfacesRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição vs HerançaMixinsMétodos Estáticos e de ClasseDecoradores de ClasseGerenciadores de Contexto11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Propriedades de Classe
Variáveis de Instância vs de ClasseDecoradores de PropriedadeAtributos PrivadosRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Membros Públicos, Protegidos e PrivadosModificadores de AcessoOcultação de InformaçãoProperty Decorators AvançadosRecapitulação - Sistema de Registro de Alunos12Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e UsuárioSistema de EmpréstimosFuncionalidade de BuscaInterface AdministrativaTestes e IntegraçãoPratique por conta própria: Compilador de Python online