Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to call setChanged before I notify the observers?

Tags:

java

I've recently read about Java's Observable class. What I don't understand is this: before notifying the observers (notifyObservers()) I must call setChanged(). There is a boolean inside notifyObservers method that requires us to call setChanged. What is the purpose of the boolean value and why must I call setChanged()?

like image 365
Shelef Avatar asked Feb 27 '13 19:02

Shelef


People also ask

How do I notify Observer?

notifyObservers() method notify all of its observers if the object has changed. This method later calls the clearChanged method to indicate that this object has no longer changed. This method is equivalent to notifyObservers(null).

Can an Observer be observable?

An observable object can have one or more observers. An observer may be any object that implements interface Observer. After an observable instance changes, an application calling the Observable 's notifyObservers method causes all of its observers to be notified of the change by a call to their update method.

Why observable is deprecated?

Ans: The Observable class and the Observer interface have been deprecated in Java 9 because the event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications.

Why is observable not an interface?

The Subject (Observable) is a class and must be subclassed. So you run into the problem that you cannot subclass from another more important class. Java only allows single inheritance.


4 Answers

In a long treatment you may call several times setChanged() but at end, only once notifyObservers(). If, before end, for internal reason you decide to rollback you may choose to call clearChanged(). In the later case, notifyObservers() has no effect.

like image 108
Aubin Avatar answered Oct 12 '22 00:10

Aubin


setChanged()

Marks this Observable object as having been changed; the hasChanged method will now return true.

notifyObservers()

If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.

Basically you use setChanged() to notify the observer superclass that a change has occurred. Then you call the notifyObservers() method to fire off to tell observers what is changed.

The setChanged() there because it allows for a class to undo changes before notify observers by calling clearChanged(). If you didn't setChanged() flag then you are essentially notifying observers and there are no changes detected so they will not respond to the "notify".

see my code for more explanation:

The Main Method public class SpeedRunner {

public static void main(String[] args) {
    SpeedMonitor monitor = new SpeedMonitor();
    // Create a speedometer and register the monitor to it...
    SpedoMeter speedo = new SpedoMeter();
    speedo.addObserver(monitor);
    // Drive at different speeds...
    speedo.setCurrentSpeed(50);
    speedo.setCurrentSpeed(70);
    speedo.setCurrentSpeed(40);
    speedo.setCurrentSpeed(100);
    speedo.setCurrentSpeed(69);
}

The Observer (object that is informed when something interesting happens):

//this is the observer since it is observing changes in the speedo.
public class SpeedMonitor implements Observer {
public static final int SPEED_TO_ALERT = 70;

public void update(Observable obs, Object obj) {
    SpedoMeter speedo = (SpedoMeter) obs;
    if (speedo.getCurrentSpeed() > SPEED_TO_ALERT) {
        System.out.println("** ALERT ** Driving too fast! (" + speedo.getCurrentSpeed() + ")");
    } else {
        System.out.println("... nice and steady ... (" + 
        speedo.getCurrentSpeed() + ")");
        }
    }
}

The subject (the the object of interest)

public class SpedoMeter extends Observable{
private int currentSpeed;

public SpedoMeter(){
    currentSpeed = 0;
}

public void setCurrentSpeed(int speed){
    currentSpeed = speed;

//        setChanged();
    notifyObservers();
}

        public int getCurrentSpeed() {
        return currentSpeed;
    }

}

comment out the setChanged() and you will notice nothing is picked up by the observer hence the console is empty.

See this textbook. Its really good to learn design patterns.

Bevis, Tony. Java Design Pattern Essentials (Kindle Location 1835). Ability First Limited. Kindle Edition.

like image 28
Daniel Avatar answered Oct 12 '22 00:10

Daniel


the setchanged() is used as indication or flag for changing the state. if it true the notifyObservers() can run and update all the observers.if it false the notifyObservers() is called without calling the setchanged() and the observers will not be notified.

like image 30
Ramzi Hosisey Avatar answered Oct 11 '22 23:10

Ramzi Hosisey


the may reason may be setChanged() is has a protected modifier. Meanwhile, notifyObservers() could be invoked anywhere, even by a observer. Since that, observable and observer may interact with each other with this mechanism.

like image 28
tian Avatar answered Oct 11 '22 23:10

tian