O padrão Observer é um padrão de design comportamental que tem como objetivo principal estabelecer uma relação de um-para-muitos entre objetos, de forma que quando um objeto (conhecido como "subject" ou "observable") muda seu estado, todos os seus dependentes (os "observers") são notificados e atualizados automaticamente.
Este padrão é utilizado para resolver vários problemas relacionados à comunicação entre objetos:
-
Notificações de Mudanças de Estado: Em sistemas complexos, pode ser necessário que vários componentes sejam informados sobre as mudanças de estado em outro componente. O Observer facilita essa notificação sem que os componentes precisem verificar constantemente o estado uns dos outros.
-
Baixo Acoplamento: O padrão Observer promove o baixo acoplamento entre o objeto que notifica sobre as mudanças (observable) e os objetos que recebem essas notificações (observers). Os observers podem ser adicionados ou removidos dinamicamente sem alterar o observable.
-
Flexibilidade e Reutilização: Permite que diferentes observers reajam a notificações de maneira independente, possibilitando a reutilização e a extensão. Diferentes observers podem ser definidos para reagir de maneiras distintas às mesmas notificações.
-
Consistência entre Objetos Relacionados: Garante que os objetos dependentes se mantenham atualizados e consistentes com o estado do objeto observado, reduzindo a probabilidade de inconsistências no sistema.
Como Funciona
O padrão Observer envolve duas classes principais:
- Observable (Subject): O objeto que mantém uma lista de seus observers e os notifica sobre quaisquer mudanças de estado, geralmente chamando um dos seus métodos.
- Observer: Uma interface com um método de atualização que é invocado pelo Observable quando seu estado muda.
Exemplo
Um exemplo comum do uso do padrão Observer é em interfaces gráficas de usuário (GUIs), onde ações do usuário em um componente (como um botão) podem desencadear atualizações em outros componentes (como um display ou um painel de informações). Outro exemplo é em sistemas de monitoramento ou alerta, onde mudanças em condições ou dados monitorados devem ser comunicadas a diversos componentes ou sistemas interessados.
Exemplo de implementação
Vamos criar um exemplo simples do padrão Observer em Java. Vamos implementar um sistema de notificação de temperatura, onde um “Sensor de Temperatura” (Observable) notifica seus observadores (Observers) sempre que a temperatura muda.
Interface Observer
Primeiro, definimos a interface Observer que será implementada por todos os observadores:
public interface Observer {
void update(float temperatura);
}Classe Observable (Subject)
Em seguida, criamos a classe SensorTemperatura que permite que os observers se registrem e os notifica quando a temperatura muda:
import java.util.ArrayList;
import java.util.List;
public class SensorTemperatura {
private float temperatura;
private List<Observer> observers;
public SensorTemperatura() {
observers = new ArrayList<>();
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void setTemperatura(float temperatura) {
this.temperatura = temperatura;
notifyObservers();
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperatura);
}
}
}Observers Concretos
Agora, implementamos alguns observers concretos:
public class DisplayTemperatura implements Observer {
@Override
public void update(float temperatura) {
System.out.println("Display Temperatura: Temperatura atual é " + temperatura + "°C");
}
}
public class AlertaTemperatura implements Observer {
@Override
public void update(float temperatura) {
if (temperatura > 30) {
System.out.println("Alerta Temperatura: Está muito quente!");
} else if (temperatura < 10) {
System.out.println("Alerta Temperatura: Está muito frio!");
}
}
}Testando o Padrão Observer
Por fim, vamos usar o padrão Observer para monitorar as mudanças de temperatura:
public class Main {
public static void main(String[] args) {
SensorTemperatura sensor = new SensorTemperatura();
Observer display = new DisplayTemperatura();
Observer alerta = new AlertaTemperatura();
sensor.addObserver(display);
sensor.addObserver(alerta);
sensor.setTemperatura(25);
sensor.setTemperatura(35);
sensor.setTemperatura(5);
}
}Neste exemplo, SensorTemperatura é o Observable que mantém uma lista de observers e os notifica sobre mudanças na temperatura. DisplayTemperatura e AlertaTemperatura são Observers que reagem às mudanças de temperatura. Quando a temperatura é definida no sensor, ele notifica todos os seus observers. Isso demonstra como o padrão Observer permite uma comunicação eficaz entre objetos de maneira desacoplada.