Failed to get watcher pattern to work.

I tried to use the observer pattern in a relatively simple application.

I have 4 classes of GUI

  • StarterClass (contains CompositeWordLists and CompositeWordListData )
  • CompositeWordLists (contains a lot of CompositeListItem / s and a CompositeWordListData )
    • CompositeListItem
  • CompositeWordListData strong> (contains DialogWordData )
  • DialogWordData STRONG>

Here is my observed

 interface Observable<T> { void addObserver(T o); void removeObserver(T o); void removeAllObservers(); void notifyObservers(); } 

And I create Observers as follows:

 public class Observers { private Observers(){}; interface WordListsObserver { public void update(CompositeWordLists o); } interface ListItemObserver { public void update(CompositeListItem o); } } 

Basically, I have problems indicating the type of event that occurred. For example, the CompositeWordLists class needs to know when the CompositeListItem deleted, saved, edited, etc., but I only have one update method ... my brain hurts!

What is the best way to do this?


UPDATE

I'm having problems with this, I added events and changed Observable and Observers, but now I have type security issues.

 public class Observers { private Observers(){}; /** * @param <T> the object that is passed from the Observable */ interface ObservableEvent<T> { T getEventObject(); } /** * Get notified about Authentication Attempts */ interface ObserverAuthenticationAttempt { /** * @param e true if authentication was successful */ public void update(ObservableEvent<Boolean> e); } /** * Get notified about a Word Deletion */ interface ObserverWordDeleted { /** * @param e the id of the word that was deleted */ public void update(ObservableEvent<Integer> e); } } 

The Observable interface now looks like this

 interface Observable<T> { void addObserver(T o); void removeObserver(T o); void removeAllObservers(); <K> void notifyObservers(Observers.ObservableEvent<K> e); } 

The problem is that when I implement this, I get and will have to distinguish K from the corresponding type, and not from what I want to do.

 @Override public <K> void notifyObservers(ObservableEvent<K> e) { for(Observers.ObserverAuthenticationAttempt o : this.observers) o.update(e); } 

What am I doing wrong?

update 2

It actually works better with Observable, but I still need to specify the correct EventType in two different places.

 interface Observable<T,K> { void addObserver(T o); void removeObserver(T o); void removeAllObservers(); void notifyObservers(Observers.ObservableEvent<K> e); } 
+2
source share
3 answers

You do not need to parameterize the Watchers, but you need to parameterize the events.

 public interface Observer<T> { void notify(T event); } 

Example event:

 public class WordListUpateEvent { private final int changedIndex; public WordListUpateEvent(int changedIndex) { this.changedIndex = changedIndex; } public int getChangedIndex() { return changedIndex; } } 

Then you can have a different interface, for example:

 public interface WordListObserver extends Observer<WordListUpateEvent> {} 

and its implementation

 public class ConcreteWordListObserverA implements WordListObserver { @Override public void notify(WordListUpateEvent event) { System.out.println("update item at index: " + event.getChangedIndex()); } } 

on the other hand, you need your Observable interface, I split it into two interfaces to make the notifyObservers method open to observers (you'll see it later):

 public interface Observable<T> extends ObservableRegistration<T> { void notifyObservers(T event); } public interface ObservableRegistration<T> { void addObserver(Observer<T> o); void removeObserver(Observer<T> o); void removeAllObservers(); } 

If you have several observable objects, you cannot implement the Observalbe interface directly for your object, so you need a separate implementation class:

 public class ObservableImpl<T> implements Observable<T>{ private final List<Observer<T>> observers = new ArrayList<Observer<T>>(); @Override public void addObserver(Observer<T> o) { this.observers.add(o); } @Override public void removeObserver(Observer<T> o) { this.observers.remove(o); } @Override public void removeAllObservers() { this.observers.clear(); } @Override public void notifyObservers(T event) { for(Observer<T> observer : observers) { observer.notify(event); } } } 

Now you can use the implementation in your topic:

 public class Subject { private Observable<WordListUpateEvent> wordListObservable = new ObservableImpl<WordListUpateEvent>(); //private Subject<OtherEvent> otherObservable = new ObservableImpl<WordListUpateEvent>(); public ObservableRegistration<WordListUpateEvent> getWordListObservableRegistration() { return this.wordListObservable; } // public ObservableRegistration<OtherEvent> getOtherRegistration() { // return this.otherObservable; // } public void doSomething() { this.wordListObservable.notifyObservers(new WordListUpateEvent(42)); } } 

And here is how you can connect the observer and the subject:

 public class Start { public static void main(String[] args) { Subject subject = new Subject(); subject.getWordListObservableRegistration().addObserver(new ConcreteWordListObserverA()); subject.getWordListObservableRegistration().addObserver(new ConcreteWordListObserverA()); subject.doSomething(); } } 
+3
source

I would create an Observer interface containing a public void update(ObservableEvent oe) method and an ObserverEvent interface. After that, you can create a specific class for each of your events.

0
source

http://download.oracle.com/javase/1.4.2/docs/api/java/util/Observer.html
http://www.java2s.com/Code/Java/Design-Pattern/Observableandobserver.htm

The Java Observer update method has an Object argument. You can transfer any object, so you can create your own UpdateMessage object, which can contain an updated object and additional information about what happened (deleted, saved, etc.).

0
source

Source: https://habr.com/ru/post/1416146/


All Articles