2

I have read a book named "Head First Pattern" and have a question about pattern "Observer".

How should an observer subscribe on observable if it's API include only 1 method "update()"?

Firstly, I assume that observer it must contain method "subscribe(Observable observable)"

How to implement a mechanism of subscription in the best way?

  • I've just posted answer to a similar question on the same page (couple of minutes ago): https://stackoverflow.com/questions/47614003/observer-pattern-update-parameters/47614147#47614147 – LowLevel Dec 03 '17 at 00:56

2 Answers2

3

Actually, it's the other way around. You attach or add an Observer to an object that will be observed, an Observable. You do that so that the observed object is able to notify the observers once its state has changed.

In this pattern, if you were to subscribe a Subject in an observer object and only do that. How could the observer know when the subject's state was changed the moment the action took place? Maybe the observer could start polling and asking about the subject's state until it changes and then the observer would act on it. But that is far from ideal.

That is kind of what happens with a WatchService in which you, for instance, add a file to a service in order to be notified once the file is modified. Roughly, you're "subscribing" the subject in the observer. But here, you start a service that will take care of what you need behind the curtains.

Anyway, in your case, the best way would be to let the subject object manage the observers and call it whenever is appropriate.

Check out this link: https://sourcemaking.com/design_patterns/observer

You must implement your class Subject so that it receives entities that will observe its behavior and be notified as desired. It's the Subject's duty to notify the observers when a desired change has been made.

Java has its own implementation of the pattern. You should start by reading the Observable class to get the gist of it. Then, you should implement your own following the guidelines you've read. The idea is like this:

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

public class TestObserver {
    public static void main(String[] args) {
        Subject subject = new Subject();
        ContentObserver contentObs = new ContentObserver();
        subject.addObserver(contentObs);
        // Once you call setContent, the object contentObs
        // will be notified and print the desired text
        subject.setContent("test");
    }
}

class Subject {

    private String content;

    private List<ContentObserver> observers = new ArrayList<>();

    public void addObserver(ContentObserver obs) {
        observers.add(obs);
    }

    public void setContent(String content) {
        this.content = content;
        notifyContentObservers();
    }

    private void notifyContentObservers() {
        observers.forEach(obs -> obs.update(content));
    }

}

class ContentObserver {

    public void update(String content) {
        System.out.println("Content was changed! New content = " + content);
    }

}

Remember that this is an example. You must manage your observers by adding, removing, etc. It's also advisable to code to an interface, so you should create your own Observer interface according to what you want to observe.

Also, you shouldn't use the implementation provided by java as it's deprecated in java 9: https://docs.oracle.com/javase/9/docs/api/java/util/Observable.html https://dzone.com/articles/javas-observer-and-observable-are-deprecated-in-jd

If you want something more reliable and reactive. Take a look at: https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html

Cheers!

wleao
  • 2,316
  • 1
  • 18
  • 17
  • Thank you! I am just wondering why 'ContentObserver' doesn't have the method 'subscribe'? What should an object do if it wants to become an observer of any Subject? –  Dec 03 '17 at 02:17
  • It should be added in the list of observers of the Subject. For instance, in my example, through this call: subject.addObserver(contentObs) – wleao Dec 03 '17 at 02:26
  • yes. but following the pattern is it possible to add a method to an observer similar to subscribe(Subject s) {s.addObserver(this);} ? –  Dec 03 '17 at 03:51
  • oh! I got you now! The problem with that is if you subscribe a subject in the observer and only do that. How will the observer know when the subject's state was changed? If the observer is the one responsive of managing the subjects he will never be notified if the subject doesn't have a way to notify the observer. Did I make myself clear now? I think I understand what you're thinking. – wleao Dec 03 '17 at 10:39
  • I've edited my answer and expanded the explanation. Take a look and tell me what you think. Cheers! – wleao Dec 03 '17 at 10:52
0
 observable.addObserver(observer);
 // now when observable changes, the observer will know
Edwin Buck
  • 69,361
  • 7
  • 100
  • 138