O padrão observador é um padrão de design comportamental. O uso do padrão Observer é quando você está interessado no estado de um objeto e deseja ser notificado sempre que ele mudar. No padrão observador, o objeto que observa o estado de outro objeto é chamado de Observador, e o objeto observado é chamado de Sujeito. De acordo com as regras do GoF, a intenção do padrão Observer é:
Copie o código do código da seguinte forma:
Defina um relacionamento de dependência um-para-muitos entre objetos. Se o estado de um objeto mudar, outros objetos relacionados serão notificados e atualizados automaticamente.
Os assuntos contêm observadores que precisam ser notificados quando seu estado muda. Portanto, deve fornecer aos observadores métodos para se registarem e cancelarem o registo. Quando o Assunto (observado) muda, também precisa incluir um método para notificar todos os observadores. Ao notificar os observadores, você pode enviar atualizações por push ou fornecer outro método para obter atualizações.
Os observadores devem ter um método que defina o objeto observador e possa ser usado pelo observado para notificá-lo sobre atualizações.
JAVA fornece maneiras integradas de implementar o padrão observador, as interfaces java.util.Observable e java.util.Observer. No entanto, eles não são muito utilizados. Como essa implementação é muito simples, na maioria das vezes não queremos que a última classe estendida implemente apenas o padrão observador, porque as classes JAVA não podem herdar várias vezes.
O serviço de mensagens Java Messages Service (JMS) usa o modo observador e o modo de comando para realizar a publicação e assinatura de dados entre diferentes programas.
A estrutura MVC modelo-visão-controle também usa o padrão observador, tratando o modelo como observado e a visão como observador. As visualizações podem se registrar no modelo para receber alterações no modelo.
Exemplo de padrão de observador
Neste exemplo, concluiremos uma discussão de tópico simples e os observadores poderão se registrar neste tópico. Quaisquer alterações resultantes do envio de conteúdo sobre este tópico serão notificadas a todos os observadores registrados.
Com base nas necessidades dos observadores do Assunto, trata-se de implementar uma interface básica do Assunto. Essa interface especifica uma série de métodos específicos que precisam ser implementados na classe específica que posteriormente implementa a interface.
Copie o código do código da seguinte forma:
pacote com.journaldev.design.observer;
interface pública Assunto {
//métodos para registrar e cancelar o registro de observadores
registro público vazio (Observador obj);
cancelamento de registro público void (Observador obj);
//método para notificar os observadores sobre mudanças
public void notifyObservers();
//método para obter atualizações do assunto
objeto público getUpdate (Observador obj);
}
Agora crie um observador associado. É necessário um método para anexar o Assunto a um observador. Métodos adicionais podem aceitar notificações de alteração de assunto.
Copie o código do código da seguinte forma:
pacote com.journaldev.design.observer;
interface pública Observador {
//método para atualizar o observador, usado pelo sujeito
atualização pública vazia();
//anexar com assunto para observar
public void setSubject(Assunto sub);
}
Esta conexão foi estabelecida. Agora implemente o tema concreto.
Copie o código do código da seguinte forma:
pacote com.journaldev.design.observer;
importar java.util.ArrayList;
importar java.util.List;
classe pública MyTopic implementa Assunto {
private List<Observador> observadores;
mensagem de string privada;
booleano privado alterado;
objeto final privado MUTEX= new Object();
público MeuTópico(){
this.observers=new ArrayList<>();
}
@Substituir
registro público vazio (Observador obj) {
if(obj == null) throw new NullPointerException("Observador Nulo");
if(!observers.contains(obj)) observadores.add(obj);
}
@Substituir
public void cancelar registro(Observador obj) {
observadores.remove(obj);
}
@Substituir
public void notifyObservers() {
List<Observador> observadoresLocal = null;
//a sincronização é usada para garantir que qualquer observador registrado após o recebimento da mensagem não seja notificado
sincronizado (MUTEX) {
se (! alterado)
retornar;
observadoresLocal = new ArrayList<>(this.observers);
this.changed=false;
}
for (Observador obj: observadoresLocal) {
obj.update();
}
}
@Substituir
objeto público getUpdate(Observador obj) {
retorne esta.mensagem;
}
//método para postar mensagem no tópico
public void postMessage(String mensagem){
System.out.println("Mensagem postada no tópico:"+msg);
esta.mensagem=msg;
this.changed=true;
notificarObservadores();
}
}
A implementação dos métodos de registro e cancelamento de registro é muito simples. O método adicional postMessage() será usado pelo cliente para enviar uma mensagem de string para este tópico. Observe que variáveis booleanas são usadas para rastrear alterações no estado do tópico e notificar os observadores sobre tais alterações. Esta variável é necessária porque se não houver atualização, mas alguém chamar o método notifyObservers(), ele não poderá enviar informações de notificação de erro aos observadores.
Além disso, deve-se observar que a sincronização é usada em notifyObservers() para garantir que as notificações só possam ser enviadas aos observadores registrados antes da mensagem ser publicada no tópico.
Aqui está a implementação do observador. Eles sempre focarão no objeto em questão.
Copie o código do código da seguinte forma:
pacote com.journaldev.design.observer;
classe pública MyTopicSubscriber implementa Observer {
nome da string privada;
tópico de assunto privado;
public MyTopicSubscriber(String nm){
este.nome=nm;
}
@Substituir
atualização pública void() {
String msg = (String) topic.getUpdate(this);
if(mensagem==nulo){
System.out.println(name+":: Nenhuma nova mensagem");
}outro
System.out.println(name+":: Consumindo mensagem::"+msg);
}
@Substituir
public void setSubject(Assunto sub) {
este.topic=sub;
}
}
Observe que a implementação do método update() usa getUpdate() do observador para lidar com mensagens atualizadas. Passar a mensagem como parâmetro para o método update() deve ser evitado aqui.
Aqui está um programa de teste simples para verificar a implementação da classe de tópico.
Copie o código do código da seguinte forma:
pacote com.journaldev.design.observer;
classe pública ObserverPatternTest {
public static void main(String[] args) {
//cria assunto
Tópico MeuTópico = new MeuTópico();
//cria observadores
Observador obj1 = new MyTopicSubscriber("Obj1");
Observador obj2 = new MyTopicSubscriber("Obj2");
Observador obj3 = new MyTopicSubscriber("Obj3");
//cadastra observadores para o assunto
tópico.register(obj1);
tópico.register(obj2);
tópico.register(obj3);
//anexa o observador ao assunto
obj1.setSubject(tópico);
obj2.setSubject(tópico);
obj3.setSubject(tópico);
//verifica se alguma atualização está disponível
obj1.atualização();
//agora envia mensagem para o assunto
topic.postMessage("Nova Mensagem");
}
}
Aqui está a saída acima:
Copie o código do código da seguinte forma:
Obj1:: Nenhuma nova mensagem
Mensagem postada no tópico:Nova mensagem
Obj1::Consumindo mensagem::Nova mensagem
Obj2::Consumindo mensagem::Nova mensagem
Obj3::Consumindo mensagem::Nova mensagem</pre>
Diagrama UML do padrão Observer
O padrão observador também é chamado de padrão publicar-assinar. Algumas aplicações específicas em JAVA são as seguintes:
1.java.util.EventListener em Swing
2.javax.servlet.http.HttpSessionBindingListener
3.javax.servlet.http.HttpSessionAttributeListener
Os itens acima são todos modos de observador. Espero que você já goste. Compartilhe seus sentimentos nos comentários ou compartilhe com outras pessoas.