无法使观察者模式工作

时间:2010-11-26 07:35:11

标签: java observer-pattern

我一直试图让观察者模式在一个相对简单的应用程序中运行。

我有4个GUI类

  • StarterClass (包含CompositeWordListsCompositeWordListData
  • CompositeWordLists (包含许多CompositeListItem / s和CompositeWordListData
    • CompositeListItem
  • CompositeWordListData (包含DialogWordData
    • DialogWordData

这是我的Observable

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

我正在创建这样的观察者:

public class Observers {
    private Observers(){};

    interface WordListsObserver {
        public void update(CompositeWordLists o);
    }   

    interface ListItemObserver {
        public void update(CompositeListItem o);
    }
}

基本上我在指定发生的事件类型方面遇到了麻烦。例如,CompositeWordLists类需要知道何时删除CompositeListItem,保存编辑等,但我只有一种更新方法......我的大脑现在受伤了!

这样做的更好方法是什么?


更新

仍有问题,我添加了事件并更改了Observable和Observers,但现在我遇到了类型安全问题。

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); 
    }
}

Observable Interface现在看起来像这样

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

问题在于,当我实现这个时,我得到并且必须将K转换为适当的类型,而不是我想要做的。

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

我做错了什么?

更新2

实际上它对于像这样的Observable效果更好,但我仍然需要在两个不同的地方指定正确的EventType。

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

3 个答案:

答案 0 :(得分:3)

您无需对观察者进行参数化,但您需要对事件进行参数化。

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

一个示例事件:

public class WordListUpateEvent {

    private final int changedIndex;

    public WordListUpateEvent(int changedIndex) {       
        this.changedIndex = changedIndex;
    }

    public int getChangedIndex() {
        return changedIndex;
    }
}

然后你可以有不同的界面,例如:

public interface WordListObserver extends Observer<WordListUpateEvent> {}

及其实现

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

另一方面,你需要你的Observable接口,我已经将它拆分为两个接口,以使notifyObservers方法不公开给观察者(你稍后会看到):

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();
}

如果你在一个主题中有几个observable,你就不能直接向你的主题实现Observalbe接口,所以你需要一个单独的实现类:

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);
        }
    }

}

现在您可以在主题中使用该实现:

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));
    }

}

这就是你如何连接观察者和主题:

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();
    }
}

答案 1 :(得分:0)

我将创建一个包含public void update(ObservableEvent oe)方法的Observer接口和一个ObserverEvent接口。之后,您可以为每个活动创建特定的课程。

答案 2 :(得分:0)

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

Java Observer的update方法具有Object参数。您可以传递任何Object,因此您可以创建自己的“UpdateMessage”对象,该对象可以包含更新的对象以及有关所发生事件(已删除,已保存等)的其他信息。