Когда следует использовать Observer и Observable

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

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

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

1) Observable – это class, а Observer – интерфейс.

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

3) Когда объект Observable обновляется, он вызывает метод 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) для?

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

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

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

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

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

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

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

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

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

ОБНОВИТЬ

В ответ на ваш комментарий настоящий class java.util.Observable предлагает следующие возможности:

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

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

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

Определение

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

Примеры

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

  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

Создать class темы.

Subject.java

  import java.util.ArrayList; import java.util.List; public class Subject { private List observers = new ArrayList(); 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

Создать class Observer.

Observer.java

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

Шаг 3

Создание конкретных classов наблюдателей

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

Используйте объекты Subject и конкретные объекты-наблюдатели.

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

Hex String: F

Октальная строка: 17

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

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

Hex String: A

Октальная строка: 12

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

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

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

Наблюдатель aka callback зарегистрирован в Observable.

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

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

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

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

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

 interface MyObserver { void update(MyObservable o, Object arg); } 

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

 class MyObservable { ArrayList myObserverList = new ArrayList(); 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); } } 

«Я попытался выяснить, почему именно нам нужен Наблюдатель и Наблюдаемый»

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

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

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

Я также нашел эту статью на начальной странице Visual Studio 2008 ( The Observer Pattern является основой для разработки Model View Controller (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

Отрывок из сообщения:

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

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

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

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

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

Однако вы можете получить интервью о них …

  • std :: enable_if условно скомпилировать функцию-член
  • C ++ шаблоны Turing-complete?
  • Ошибка «Undefined symbols» с компоновщиком простого шаблона
  • Ограничить переменные аргументы шаблона
  • HTML5: Почему мой атрибут oninvalid позволяет шаблону выйти из строя?
  • Расшифровка сообщений об ошибках шаблона C ++
  • Получить индекс типа элемента кортежа?
  • Что такое «выражение SFINAE»?
  • C ++ вызывает явный конструктор шаблонов
  • Как убедиться, что параметр шаблона является подтипом требуемого типа?
  • JQuery's $ находится в конфликте с StringTemplate.Net в ASP.Net MVC
  • Давайте будем гением компьютера.