Quando devemos usar o Observer e o Observable?

200

Um entrevistador me perguntou:

O que é Observere Observablequando devemos usá-los?

Eu não estava ciente desses termos, então quando eu cheguei em casa para trás e começou pesquisando sobre Observere Observable, eu encontrei alguns pontos de diferentes recursos:

1) Observableé uma classe e Observeré uma interface.

2) A Observableclasse mantém uma lista de Observers.

3) Quando um Observableobjeto é atualizado, ele invoca o update()método de cada um de seus Observers para notificar que ele é alterado.

Encontrei este exemplo:

import java.util.Observable;
import java.util.Observer;

class MessageBoard extends Observable
{
    public void changeMessage(String message) 
    {
        setChanged();
        notifyObservers(message);
    }
}

class Student implements Observer 
{
    @Override
    public void update(Observable o, Object arg) 
    {
        System.out.println("Message board changed: " + arg);
    }
}

public class MessageBoardTest 
{
    public static void main(String[] args) 
    {
        MessageBoard board = new MessageBoard();
        Student bob = new Student();
        Student joe = new Student();
        board.addObserver(bob);
        board.addObserver(joe);
        board.changeMessage("More Homework!");
    }
}

Mas eu não entendo por que precisamos Observere Observable? Quais são os métodos setChanged()e notifyObservers(message)?

Ravi
fonte
O link não está funcionando. @Androider Você pode fornecer um link atualizado?
Prateek # 24/15
Se você estiver usando Java 6 ou acima, em seguida, tentar este dzone.com/articles/java-ee6-events-lightweight
Ramiz Uddin
1
Eu sugeriria a leitura deste livro para entender bem os padrões de design. Parece bobo, mas é uma excelente ferramenta de aprendizado.
Countofmontecristo
1
Todo mundo observe isso; Observer / Observable foi descontinuado no Java 9. Alternativas: stackoverflow.com/questions/46380073/…
eren130

Respostas:

265

Você tem um exemplo concreto de um aluno e um MessageBoard. O Aluno se registra adicionando-se à lista de Observadores que desejam ser notificados quando uma nova Mensagem é postada no MessageBoard. Quando uma Mensagem é adicionada ao MessageBoard, ele itera sobre sua lista de Observadores e notifica-os de que o evento ocorreu.

Pense no Twitter. Quando você diz que deseja seguir alguém, o Twitter adiciona você à sua lista de seguidores. Quando eles enviaram um novo tweet, você o vê na sua entrada. Nesse caso, sua conta do Twitter é o Observador e a pessoa que você segue é o Observável.

A analogia pode não ser perfeita, porque é mais provável que o Twitter seja um mediador. Mas ilustra o ponto.

duffymo
fonte
57

Em termos muito simples (porque as outras respostas referem-se a todos os padrões oficiais de design de qualquer maneira, consulte-os para obter mais detalhes):

Se você deseja ter uma classe que é monitorada por outras classes no ecossistema do seu programa, você diz que deseja que a classe seja observável. Ou seja, pode haver algumas mudanças em seu estado que você deseja transmitir para o restante do programa.

Agora, para fazer isso, precisamos chamar algum tipo de método. Não queremos que a classe Observable seja fortemente acoplada às classes que estão interessadas em observá-la. Não se importa quem é, desde que cumpra determinados critérios. (Imagine que é uma estação de rádio, não importa quem está ouvindo, desde que tenha um rádio FM sintonizado em sua frequência). Para conseguir isso, usamos uma interface, conhecida como Observador.

Portanto, a classe Observable terá uma lista de Observadores (ou seja, instâncias que implementam os métodos de interface do Observer que você possa ter). Sempre que deseja transmitir algo, apenas chama o método a todos os observadores, um após o outro.

A última coisa a encerrar o quebra-cabeça é como a classe Observable saberá quem está interessado? Portanto, a classe Observable deve oferecer algum mecanismo para permitir que os Observadores registrem seu interesse. Um método como addObserver(Observer o)o adiciona internamente o Observador à lista de observadores, de modo que quando algo importante acontece, ele percorre a lista e chama o método de notificação respectivo da interface do Observador de cada instância da lista.

Pode ser que na entrevista que eles não pedir-lhe explicitamente sobre o java.util.Observere java.util.Observable, mas sobre o conceito genérico. O conceito é um padrão de design, para o qual o Java fornece suporte diretamente pronto para uso, para ajudá-lo a implementá-lo rapidamente quando necessário. Então, eu sugiro que você entenda o conceito em vez dos métodos / classes reais (que você pode procurar quando precisar deles).

ATUALIZAR

Em resposta ao seu comentário, a java.util.Observableclasse real oferece os seguintes recursos:

  1. Mantendo uma lista de java.util.Observerinstâncias. Novas instâncias interessadas em ser notificadas podem ser adicionadas addObserver(Observer o)e removidas deleteObserver(Observer o).

  2. Manter um estado interno, especificando se o objeto foi alterado desde a última notificação aos observadores. Isso é útil porque separa a parte em que você diz que Observablefoi alterada e a parte em que você notifica as alterações. (Por exemplo, é útil se você tiver várias alterações e deseja notificar apenas no final do processo, e não em cada pequena etapa). Isso é feito completamente setChanged(). Então, basta chamá-lo quando você altera algo para o Observablee deseja que o resto Observerssaiba eventualmente sobre ele.

  3. Notificando todos os observadores que o específico Observablemudou de estado. Isso é feito completamente notifyObservers(). Isso verifica se o objeto realmente mudou (ou seja, setChanged()foi feita uma chamada ) antes de prosseguir com a notificação. Existem 2 versões, uma sem argumentos e outra com um Objectargumento, caso deseje passar algumas informações extras com a notificação. Internamente, o que acontece é que ele apenas percorre a lista de Observerinstâncias e chama o update(Observable o, Object arg)método para cada uma delas. Isso indica Observerqual foi o objeto Observável que foi alterado (você pode estar observando mais de um) e o extra Object argpara potencialmente levar algumas informações extras (transmitidas notifyObservers().

jbx
fonte
37

Definição

O padrão observador é usado quando há um ou muitos relacionamentos entre objetos, como se um objeto for modificado, seus objetos dependentes serão notificados automaticamente e as alterações correspondentes serão feitas em todos os objetos dependentes.

Exemplos

  1. Digamos que seu endereço permanente seja alterado e você precisará notificar a autoridade do passaporte e a autoridade do cartão panorâmico. Portanto, aqui a autoridade de passaporte e a autoridade do cartão panorâmico são observadores e você é um sujeito.

  2. No Facebook também, se você se inscrever em alguém, sempre que novas atualizações acontecerem, você será notificado.

Quando usá-lo:

  1. Quando um objeto altera seu estado, todos os outros objetos dependentes devem alterar automaticamente seu estado para manter a consistência

  2. Quando o sujeito não sabe sobre o número de observadores que possui.

  3. Quando um objeto deve poder notificar outros objetos sem saber quem são eles.

Passo 1

Criar classe Assunto.

Subject.java

  import java.util.ArrayList;
  import java.util.List;

  public class Subject {

  private List<Observer> observers 
        = new ArrayList<Observer>();
  private int state;

  public int getState() {
    return state;
  }

 public void setState(int state) {
   this.state = state;
   notifyAllObservers();
 }

   public void attach(Observer observer){
     observers.add(observer);       
   }

  public void notifyAllObservers(){
    for (Observer observer : observers) {
     observer.update();
  }
}   

}

Passo 2

Crie a classe Observer.

Observer.java

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

etapa 3

Crie classes de observadores concretos

BinaryObserver.java

public class BinaryObserver extends Observer{

  public BinaryObserver(Subject subject){
     this.subject = subject;
     this.subject.attach(this);
  }

  @Override
  public void update() {
     System.out.println( "Binary String: " 
     + Integer.toBinaryString( subject.getState() ) ); 
  }

}

OctalObserver.java

public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
     this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
    System.out.println( "Octal String: " 
    + Integer.toOctalString( subject.getState() ) ); 
  }

}

HexaObserver.java

public class HexaObserver extends Observer{

  public HexaObserver(Subject subject){
    this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
     System.out.println( "Hex String: " 
    + Integer.toHexString( subject.getState() ).toUpperCase() ); 
}

}

Passo 4

Use Assunto e objetos de observador concreto.

ObserverPatternDemo.java

 public class ObserverPatternDemo {
    public static void main(String[] args) {
       Subject subject = new Subject();

       new HexaObserver(subject);
       new OctalObserver(subject);
       new BinaryObserver(subject);

       System.out.println("First state change: 15");    
       subject.setState(15);
       System.out.println("Second state change: 10");   
       subject.setState(10);
 }

}

Etapa 5

Verifique a saída.

Primeira mudança de estado: 15

Sequência hexadecimal: F

Corda Octal: 17

Sequência binária: 1111

Segunda mudança de estado: 10

Sequência hexagonal: A

Corda Octal: 12

Cadeia binária: 1010

Mubarak
fonte
bem explicado :)
roottraveller 12/10
3
Eu acho que "Defination" é um erro de digitação. Espero que seja um erro de digitação.
precisa
10

Eles fazem parte do padrão de design do Observer . Normalmente, um ou mais observadores são informados sobre mudanças em um observável . É uma notificação de que "algo" aconteceu, onde você como programador pode definir o que "algo" significa.

Ao usar esse padrão, você separa as duas entidades uma da outra - os observadores se tornam plugáveis.

Andy
fonte
Eu aprecio, se você adicionar a explicação board.changeMessage("More Homework!");na sua resposta, quero dizer o que acontece quando changeMessage("More Homework!");invocado.
Ravi
9

O observador aka retorno de chamada é registrado no Observable.

É usado para informar, por exemplo, sobre eventos que aconteceram em algum ponto do tempo. É amplamente utilizado em Swing, Ajax, GWT para despachar operações em, por exemplo, eventos da interface do usuário (cliques no botão, campos de texto alterados etc.).

No Swing, você encontra métodos como addXXXListener (Listener l), no GWT você tem retornos de chamada (Async).

Como a lista de observadores é dinâmica, os observadores podem registrar e cancelar o registro durante o tempo de execução. Também é uma boa maneira de desacoplar observável dos observadores, pois as interfaces são usadas.

Pawel Solarski
fonte
9

Se o entrevistador solicitar a implementação do padrão de design do Observer sem usar classes e interfaces do Observer, você poderá usar o seguinte exemplo simples!

MyObserver como interface de observador

interface MyObserver {

    void update(MyObservable o, Object arg);
}

Classe MyObservable as Observable

class MyObservable
{
    ArrayList<MyObserver> myObserverList = new ArrayList<MyObserver>();

    boolean changeFlag = false;

    public void notifyObservers(Object o)
    {
        if (hasChanged())
        {
            for(MyObserver mo : myObserverList) {
                mo.update(this, o);
            }
            clearChanged();
        }
    }


    public void addObserver(MyObserver o) {
        myObserverList.add(o);        
    }

    public void setChanged() {
        changeFlag = true;
    }

    public boolean hasChanged() {
        return changeFlag;
    }

    protected void clearChanged() {
        changeFlag = false;
    }

    // ...
}

Seu exemplo com MyObserver e MyObservable!

class MessageBoard extends MyObservable {
  private String message;

  public String getMessage() {
    return message;
  }

  public void changeMessage(String message) {
    this.message = message;
    setChanged();
    notifyObservers(message);
  }

  public static void main(String[] args) {
    MessageBoard board = new MessageBoard();
    Student bob = new Student();
    Student joe = new Student();
    board.addObserver(bob);
    board.addObserver(joe);
    board.changeMessage("More Homework!");
  }
}

class Student implements MyObserver {

  @Override
  public void update(MyObservable o, Object arg) {
    System.out.println("Message board changed: " + arg);
  }

}
Habeeb Perwad
fonte
5

"Tentei descobrir por que exatamente precisamos de Observer e Observable"

Como as respostas anteriores já declararam, elas fornecem meios de contratar um observador para receber notificações automáticas de um observável.

Um exemplo de aplicativo em que isso pode ser útil é na ligação de dados , digamos que você tenha alguma interface do usuário que edite alguns dados e deseje que a interface do usuário reaja quando os dados forem atualizados, torne seus dados observáveis ​​e inscreva seus componentes de interface do usuário para os dados

Knockout.js é uma estrutura de javascript MVVM que possui um ótimo tutorial de introdução, para ver mais observáveis ​​em ação, eu realmente recomendo que você siga o tutorial. http://learn.knockoutjs.com/

Também encontrei este artigo na página inicial do Visual Studio 2008 ( The Observer Pattern é a base do desenvolvimento do Model View Controller (MVC) ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx

Eduardo Wada
fonte
3

Escrevi uma breve descrição do padrão de observador aqui: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Um trecho da postagem:

Padrão do observador: Estabelece essencialmente um relacionamento de um para muitos entre objetos e possui um design pouco acoplado entre objetos interdependentes.

Definição de livro de texto: O padrão Observer define uma dependência de um para muitos entre objetos, de modo que, quando um objeto muda de estado, todos os seus dependentes são notificados e atualizados automaticamente.

Considere um serviço de notificação de feed, por exemplo. Os modelos de assinatura são os melhores para entender o padrão do observador.

Abhishek Jain
fonte
0

O padrão observador é usado quando há um relacionamento muitos entre objetos, como se um objeto for modificado, seus objetos dependentes serão notificados automaticamente.

Swapnil Sharma
fonte