问题
An interviewer asked me:
What is Observer
and Observable
and when should we use them?
I wasn\'t aware of these terms, so when I got back home and started Googling about Observer
and Observable
, I found some points from different resources:
1) Observable is a class and Observer is an interface.
2) The
Observable
class maintains a list ofObserver
s.3) When an
Observable
object is updated, it invokes theupdate()
method of each of itsObserver
s to notify that, it is changed.
I found this example:
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!\");
}
}
But I don\'t understand why we need Observer
and Observable
? What are the setChanged()
and notifyObservers(message)
methods for?
回答1:
You have a concrete example of a Student and a MessageBoard. The Student registers by adding itself to the list of Observers that want to be notified when a new Message is posted to the MessageBoard. When a Message is added to the MessageBoard, it iterates over its list of Observers and notifies them that the event occurred.
Think Twitter. When you say you want to follow someone, Twitter adds you to their follower list. When they sent a new tweet in, you see it in your input. In that case, your Twitter account is the Observer and the person you're following is the Observable.
The analogy might not be perfect, because Twitter is more likely to be a Mediator. But it illustrates the point.
回答2:
In very simple terms (because the other answers are referring you to all the official design patterns anyway, so look at them for further details):
If you want to have a class which is monitored by other classes in the ecosystem of your program you say that you want the class to be observable. I.e. there might be some changes in its state which you would want to broadcast to the rest of the program.
Now, to do this we have to call some kind of method. We don't want the Observable class to be tightly coupled with the classes that are interested in observing it. It doesn't care who it is as long as it fulfils certain criteria. (Imagine it is a radio station, it doesn't care who is listening as long as they have an FM radio tuned on their frequency). To achieve that we use an interface, referred to as the Observer.
Therefore, the Observable class will have a list of Observers (i.e. instances implementing the Observer interface methods you might have). Whenever it wants to broadcast something, it just calls the method on all the observers, one after the other.
The last thing to close the puzzle is how will the Observable class know who is interested?
So the Observable class must offer some mechanism to allow Observers to register their interest. A method such as addObserver(Observer o)
internally adds the Observer to the list of observers, so that when something important happens, it loops through the list and calls the respective notification method of the Observer interface of each instance in the list.
It might be that in the interview they did not ask you explicitly about the java.util.Observer
and java.util.Observable
but about the generic concept. The concept is a design pattern, which Java happens to provide support for directly out of the box to help you implement it quickly when you need it. So I would suggest that you understand the concept rather than the actual methods/classes (which you can look up when you need them).
UPDATE
In response to your comment, the actual java.util.Observable class offers the following facilities:
Maintaining a list of
java.util.Observer
instances. New instances interested in being notified can be added throughaddObserver(Observer o)
, and removed throughdeleteObserver(Observer o)
.Maintaining an internal state, specifying whether the object has changed since the last notification to the observers. This is useful because it separates the part where you say that the
Observable
has changed, from the part where you notify the changes. (E.g. Its useful if you have multiple changes happening and you only want to notify at the end of the process rather than at each small step). This is done throughsetChanged()
. So you just call it when you changed something to theObservable
and you want the rest of theObservers
to eventually know about it.Notifying all observers that the specific
Observable
has changed state. This is done throughnotifyObservers()
. This checks if the object has actually changed (i.e. a call tosetChanged()
was made) before proceeding with the notification. There are 2 versions, one with no arguments and one with anObject
argument, in case you want to pass some extra information with the notification. Internally what happens is that it just iterates through the list ofObserver
instances and calls the update(Observable o, Object arg) method for each of them. This tells theObserver
which was the Observable object that changed (you could be observing more than one), and the extraObject arg
to potentially carry some extra information (passed throughnotifyObservers()
.
回答3:
Definition
Observer pattern is used when there is one to many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically and corresponding changes are done to all dependent objects.
Examples
Let's say, your permanent address is changed then you need to notify passport authority and pan card authority. So here passport authority and pan card authority are observers and You are a subject.
On Facebook also, If you subscribe to someone then whenever new updates happen then you will be notified.
When to use it:
When one object changes its state, then all other dependents object must automatically change their state to maintain consistency
When the subject doesn't know about the number of observers it has.
When an object should be able to notify other objects without knowing who objects are.
Step 1
Create Subject class.
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();
}
}
}
Step 2
Create Observer class.
Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
Step 3
Create concrete observer classes
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() );
}
}
Step 4
Use Subject and concrete observer objects.
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);
}
}
Step 5
Verify the output.
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
回答4:
They are parts of the Observer design pattern. Usually one or more obervers get informed about changes in one observable. It's a notifcation that "something" happened, where you as a programmer can define what "something" means.
When using this pattern, you decouple the both entities from each another - the observers become pluggable.
回答5:
Observer a.k.a callback is registered at Observable.
It is used for informing e.g. about events that happened at some point of time. It is widely used in Swing, Ajax, GWT for dispatching operations on e.g. UI events (button clicks, textfields changed etc).
In Swing you find methods like addXXXListener(Listener l), in GWT you have (Async)callbacks.
As list of observers is dynamic, observers can register and unregister during runtime. It is also a good way do decouple observable from observers, as interfaces are used.
回答6:
If the interviewer asks to implement Observer design pattern without using Observer classes and interfaces, you can use the following simple example!
MyObserver as observer interface
interface MyObserver {
void update(MyObservable o, Object arg);
}
MyObservable as Observable class
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;
}
// ...
}
Your example with MyObserver and 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);
}
}
回答7:
"I tried to figure out, why exactly we need Observer and Observable"
As previous answers already stated, they provide means of subscribing an observer to receive automatic notifications of an observable.
One example application where this may be useful is in data binding, let's say you have some UI that edits some data, and you want the UI to react when the data is updated, you can make your data observable, and subscribe your UI components to the data
Knockout.js is a MVVM javascript framework that has a great getting started tutorial, to see more observables in action I really recommend going through the tutorial. http://learn.knockoutjs.com/
I also found this article in Visual Studio 2008 start page (The Observer Pattern is the foundation of Model View Controller (MVC) development) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in-net.aspx
回答8:
I have written a short description of the observer pattern here: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html
A snippet from the post:
Observer Pattern : It essentially establishes a one-to-many relationship between objects and has a loosely coupled design between interdependent objects.
TextBook Definition: The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
Consider a feed notification service for example. Subscription models are the best to understand the observer pattern.
回答9:
Observer pattern is used when there is one-to-many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically.
回答10:
Since Java9, both interfaces are deprecated, meaning you should not use them anymore. See Observer is deprecated in Java 9. What should we use instead of it?
However, you might still get interview questions about them...
来源:https://stackoverflow.com/questions/13744450/when-should-we-use-observer-and-observable