Aprenda a implementar o padrão Observer em Java
O padrão de projeto Observer é um dos padrões mais utilizados no desenvolvimento de software, especialmente em aplicações com interface gráfica ou que envolvem eventos e atualizações frequentes de dados. Este padrão permite que objetos observadores sejam notificados quando um objeto observado sofre mudanças em seu estado interno, tornando possível a atualização de outros objetos dependentes desse estado.
Quando utilizar o padrão Observer?
O padrão Observer é útil em situações onde é necessário manter um conjunto de objetos sincronizados com o estado de outro objeto. Por exemplo, em um sistema de estoque, podemos ter um objeto "Produto" que armazena informações sobre um produto, como seu nome, preço e quantidade em estoque. Se vários objetos dependem dessas informações, como uma tela de exibição de produtos, um objeto de carrinho de compras e um objeto de histórico de vendas, é importante manter todos esses objetos sincronizados com o estado do objeto "Produto". É aqui que o padrão Observer entra em ação.
Como funciona o padrão Observer?
O padrão Observer é composto por dois tipos de objetos: o sujeito observado e os observadores. O sujeito observado é o objeto que contém o estado interno a ser monitorado, enquanto os observadores são objetos que precisam ser notificados quando esse estado interno é alterado.
O sujeito observado mantém uma lista de observadores registrados e fornece métodos para adicionar e remover observadores dessa lista. Quando o estado interno do sujeito observado muda, ele notifica todos os observadores registrados, que então atualizam seu próprio estado interno de acordo com o novo estado do sujeito.
Exemplo de código em Java:
Vamos considerar um exemplo de implementação do padrão Observer em Java. Suponha que temos um objeto "Produto" que representa um produto em um sistema de estoque, e queremos que vários outros objetos sejam notificados sempre que o estado desse produto mudar. Para isso, vamos criar uma classe "Produto" que implementa o sujeito observado, e uma classe "TelaDeExibicaoDeProduto" que implementa um observador.
Interface ObservadorDeProduto:
public interface ObservadorDeProduto {
void atualizar(Produto produto);
}
A interface ObservadorDeProduto possui apenas um método, "atualizar()", que é chamado pelo sujeito observado quando o estado interno do objeto mudar. Como parâmetro, este método recebe o objeto "Produto" atualizado, permitindo que o observador obtenha as informações necessárias para atualizar seu próprio estado interno. Os observadores concretos implementam esta interface e fornecem uma implementação específica para o método "atualizar()".
Classe Produto:
import java.util.ArrayList;
import java.util.List;
public class Produto {
private String nome;
private double preco;
private int quantidade;
private List<ObservadorDeProduto> observadores = new ArrayList<>();
public Produto(String nome, double preco, int quantidade) {
this.nome = nome;
this.preco = preco;
this.quantidade = quantidade;
}
public void adicionarObservador(ObservadorDeProduto obs) {
observadores.add(obs);
}
public void removerObservador(ObservadorDeProduto obs) {
observadores.remove(obs);
}
public void notificarObservadores() {
for (ObservadorDeProduto obs : observadores) {
obs.atualizar(this);
}
}
public void setPreco(double novoPreco) {
this.preco = novoPreco;
notificarObservadores();
}
public void setQuantidade(int novaQuantidade) {
this.quantidade = novaQuantidade;
notificarObservadores();
}
}
A classe "Produto" é o sujeito observado, que mantém uma lista de observadores (objetos que implementam a interface "ObservadorDeProduto"). Quando o preço ou a quantidade do produto são atualizados, a classe "Produto" chama o método "notificarObservadores()", que por sua vez chama o método "atualizar()" de cada observador registrado na lista.
Classe TelaDeExibicaoDeProduto:
public class TelaDeExibicaoDeProduto implements ObservadorDeProduto {
private Produto produto;
public TelaDeExibicaoDeProduto(Produto produto) {
this.produto = produto;
produto.adicionarObservador(this);
}
@Override
public void atualizar(Produto produto) {
System.out.println("Atualizando tela de exibição do produto: " + produto.getNome() + " - Preço: " + produto.getPreco() + " - Quantidade em estoque: " + produto.getQuantidade());
}
}
A classe "TelaDeExibicaoDeProduto" é um exemplo de observador, que implementa a interface "ObservadorDeProduto". Quando um objeto "TelaDeExibicaoDeProduto" é criado, ele se registra como observador do objeto "Produto" passado como parâmetro no construtor. Quando o método "atualizar()" é chamado, a tela de exibição do produto é atualizada com as informações mais recentes do objeto "Produto".
Conclusão
O padrão Observer é uma ferramenta poderosa para manter objetos dependentes sincronizados com o estado interno de outros objetos em uma aplicação. Quando usado corretamente, o padrão Observer pode ajudar a melhorar a modularidade e a escalabilidade do código, tornando-o mais fácil de entender, modificar e manter. O exemplo de código Java apresentado aqui é apenas um dos muitos casos de uso possíveis para este padrão, e é importante lembrar que a escolha de padrões de projeto deve ser baseada nas necessidades específicas de cada projeto.