Когда мы должны использовать Observer и Observable

интервьюер спросил меня:

что это Observer и Observable и когда мы должны использовать их?

Я не знал об этих терминах, поэтому, когда я вернулся домой и начал гуглить о Observer и Observable и нашел несколько точек из разных ресурсов:

1) Observable класс а Observer - это интерфейс.

2) Observable класс поддерживает список Наблюдатели.

3) при обновлении наблюдаемого объекта он вызывает update() метод каждого из его наблюдателей, чтобы уведомить, что он изменен.

я нашел этот пример:

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!");
    }
}

но я не понимаю, зачем нужны Observer и Observable? Какие setChanged() и notifyObservers(message) методы?

10 ответов


У вас есть конкретный пример студента и доски сообщений. Студент регистрируется, добавляя себя в список наблюдателей, которые хотят получать уведомления при отправке нового сообщения на доску сообщений. При добавлении сообщения в MessageBoard оно выполняет итерацию по списку наблюдателей и уведомляет их о произошедшем событии.

Подумайте Twitter. Когда вы говорите, вы хотите следовать за кем-то, Twitter добавляет вас в свой список подписчиков. Когда они отправили новый твит, вы видите это в вашем вводе. В этом случае ваша учетная запись Twitter является наблюдателем, а человек, за которым вы следуете, является наблюдаемым.

аналогия может быть не идеальной, потому что Twitter, скорее всего, будет посредником. Но это иллюстрирует суть.


в очень простых терминах (потому что другие ответы ссылаются на все официальные шаблоны дизайна в любом случае, поэтому посмотрите на них для получения дополнительной информации):

если вы хотите иметь класс, который контролируется другими классами в экосистеме вашей программы, вы говорите, что хотите, чтобы класс был наблюдаемым. Т. е. могут быть некоторые изменения в его состоянии, которые вы хотели бы транслировать остальной части программы.

теперь, чтобы сделать это, мы должны вызвать какой-то метод. Мы не хотим, чтобы наблюдаемый класс был тесно связан с классами, которые заинтересованы в его наблюдении. Ему все равно, кто он, пока он соответствует определенным критериям. (Представьте, что это радиостанция, ей все равно, кто слушает, пока у них есть FM-радио, настроенное на их частоту). Для достижения этого мы используем интерфейс, называемый наблюдателем.

таким образом, наблюдаемый класс будет иметь список наблюдателей (т. е. экземпляров, реализующих Методы интерфейса наблюдателя, которые у вас могут быть). Всякий раз, когда он хочет транслировать что-то, он просто вызывает метод на всех наблюдателях, один за другим.

последнее, что нужно закрыть головоломку, - это как наблюдаемый класс узнает, кто заинтересован? Таким образом, наблюдаемый класс должен предложить некоторый механизм, позволяющий наблюдателям регистрировать свой интерес. Такой метод, как addObserver(Observer o) внутренне добавление наблюдателя в список наблюдателей, так что, когда происходит что-то важное, он повторяется через список и вызывает соответствующий метод уведомления интерфейса наблюдателя каждого экземпляра в списке.

возможно, в интервью они не спрашивали вас прямо о java.util.Observer и java.util.Observable но об общем понятии. Концепция-это шаблон дизайна, который Java предоставляет поддержку непосредственно из коробки, чтобы помочь вам быстро реализовать его, когда вам это нужно. Поэтому я бы предложил, чтобы вы поняли концепцию, а не фактическую методы / классы (которые вы можете посмотреть, когда они вам понадобятся).

обновление

в ответ на ваш комментарий, фактический java.util.Observable класс предлагает следующие услуги:

  1. ведение списка java.util.Observer экземпляров. Новые экземпляры, заинтересованные в получении уведомления, могут быть добавлены через addObserver(Observer o) и удалены через deleteObserver(Observer o).

  2. поддержание внутреннего состояния, указание того, объект изменился с момента последнего уведомления наблюдателей. Это полезно, потому что он отделяет часть, где вы говорите, что Observable изменилось, из той части, где вы уведомляете об изменениях. (Например. Его полезно, если у вас есть несколько изменений, и вы хотите уведомить только в конце процесса, а не на каждом маленьком шаге). Это делается через setChanged(). Поэтому вы просто называете это, когда вы изменили что-то на Observable и вы хотите, чтобы остальные Observers чтобы в конечном итоге узнать об этом.

  3. уведомление всех наблюдателей о том, что конкретный Observable изменилось состояние. Это делается через notifyObservers(). Это проверяет, действительно ли объект изменился (т. е. вызов setChanged() было сделано), прежде чем приступить к уведомлению. Есть 2 версии, одна без аргументов и с Object аргумент, если вы хотите передать дополнительную информацию с уведомлением. Внутренне происходит то, что он просто повторяет список Observer экземпляры и вызовы update(Observable o, Object arg) метод для каждого из них. Это говорит Observer который был наблюдаемым объектом, который изменился (вы могли наблюдать более одного), и дополнительный Object arg потенциально нести некоторую дополнительную информацию (прошло через notifyObservers().


определение

шаблон наблюдателя используется, когда есть один ко многим отношениям между объектами, например, если один объект изменен, его зависимые объекты должны быть уведомлены автоматически и соответствующие изменения сделаны для всех зависимых объектов .

примеры

  1. Допустим, ваш постоянный адрес изменен, тогда вам нужно уведомить паспортный орган и пан-карты.Так вот паспорт полномочия и полномочия pan card являются наблюдателями, и вы являетесь субъектом.

  2. на Facebook также, если вы подписаться кто-то, то всякий раз, когда новые обновления происходят, то вы будете уведомлены.

когда использовать:

1. When one object changes its state,then all other dependents object must automatically change their state to maintain consistency
2. When subject doesn't know about number of observers it has.
3. When an object should be able to notify other objects without knowing who objects are.

Шаг 1

создать класс тему.

тема.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();
  }
}   

}

Шаг 2

создать Класс наблюдателей.

наблюдателя.java

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

Шаг 3

создать конкретные классы наблюдателей

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() ); 
}

}

Шаг 4

используйте предмет и конкретного наблюдателя объекты.

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);
 }

}

Шаг 5

проверить выход.

первое изменение состояния: 15

Шестнадцатеричная Строка: F

Восьмеричная Строка: 17

Двоичная Строка: 1111

второе изменение состояния: 10

Шестнадцатеричная Строка: A

Восьмеричная Строка: 12

Двоичная Строка: 1010


Они являются частями шаблон проектирования наблюдателя. Обычно один или несколько obervers получить информацию об изменениях в одно наблюдаемых. Это уведомление о том, что" что-то "произошло, где вы, как программист, можете определить, что означает" что-то".

при использовании этого шаблона вы отделяете оба объекта друг от друга - наблюдатели становятся подключаемыми.


наблюдатель a.к. обратный вызов регистрируется в Observable.

Он используется для информирования, например, о событиях, произошедших в определенный момент времени. Он широко используется в Swing, Ajax, GWT для диспетчеризации операций, например, событий пользовательского интерфейса (щелчки кнопок, текстовые поля изменены и т. д.).

в Swing вы найдете такие методы, как addXXXListener(Listener L), в GWT у вас есть (асинхронные)обратные вызовы.

в список наблюдателей является динамическим, наблюдатели могут регистрировать и отменять регистрацию во время выполнения. Это также хороший способ отделить наблюдаемое от наблюдателей, поскольку используются интерфейсы.


если интервьюер просит реализовать шаблон дизайна наблюдателя без использования классов и интерфейсов Observer вы можете использовать следующий простой пример!

MyObserver как интерфейс наблюдателя

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable как наблюдаемый класс

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;
    }

    // ...
}

ваш пример с MyObserver и 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 {
  public void update(MyObservable o, Object arg) {
    System.out.println("Message board changed: " + arg);
  }
}

Как уже говорилось в предыдущих ответах, они предоставляют средства подписки наблюдателя для получения автоматических уведомлений о наблюдаемом.

один пример приложения, где это может быть полезно в привязка данных, предположим, у вас есть пользовательский интерфейс, который редактирует некоторые данные, и вы хотите, чтобы пользовательский интерфейс реагировал при обновлении данных, вы можете сделать ваши данные наблюдаемыми и подпишитесь на компоненты пользовательского интерфейса на data

нокаут.js-это MVVM javascript framework, который имеет отличный учебник по началу работы, чтобы увидеть больше наблюдаемых в действии, я действительно рекомендую пройти учебник. http://learn.knockoutjs.com/

Я также нашел эту статью на начальной странице Visual Studio 2008 (шаблон наблюдателя является основой контроллера вида модели (MVC) развитие) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in-net.aspx


Я написал краткое описание шаблона наблюдателя здесь:http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

отрывок из поста:

шаблон наблюдателя: он по существу устанавливает отношения "один ко многим" между объектами и имеет слабо связанную конструкцию между взаимозависимыми объектами.

определение учебника: шаблон наблюдателя определяет зависимость "один ко многим" между объектами, чтобы при один объект изменяет состояние, все его иждивенцы уведомляются и обновляются автоматически.

рассмотрим службу уведомлений ленты, например. Модели подписки являются лучшими для понимания шаблона observer.


шаблон наблюдателя используется, когда существует отношение один ко многим между объектами, например, если один объект изменен, его зависимые объекты должны быть уведомлены автоматически.


поскольку Java9, оба интерфейса устарели, то есть вы не должны использовать их больше. См.Observer устарел в Java 9. Что мы должны использовать вместо него?

тем не менее, вы все равно можете получить вопросы интервью о них...