无法使观察者模式正常工作 [英] Having trouble getting the observer pattern working

查看:72
本文介绍了无法使观察者模式正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图使观察者模式在相对简单的应用程序中工作而无济于事.

I have been trying to no avail to get the observer pattern working in a relatively simple application.

我有4个GUI类

  • StarterClass (包含CompositeWordListsCompositeWordListData)
  • CompositeWordLists (包含许多CompositeListItem/s和一个CompositeWordListData)
    • CompositeListItem
    • StarterClass (contains a CompositeWordLists and a CompositeWordListData)
    • CompositeWordLists (contains many CompositeListItem/s and a CompositeWordListData)
      • CompositeListItem
      • DialogWordData

      这是我的观察

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

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

      And I am creating Observers like this:

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

      基本上,我在指定发生的事件类型时遇到了麻烦.例如,CompositeWordLists类需要知道什么时候删除CompositeListItem,保存已编辑的内容等,但是我只有一种更新方法……我的大脑现在很痛!

      Basically I am having trouble with specifying the sort of event that occurred. For example, the CompositeWordLists class needs to know when a CompositeListItem is deleted, saved edited etc but I only have one update method ... my brain hurts now!

      有什么更好的方法?

      仍然遇到麻烦,我添加了事件并更改了Observable和Observers,但是现在我遇到类型安全问题.

      Still having trouble with this, I added events and changed Observable and Observers but now I have type safety problems.

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

      问题是,当我实现此功能时,我将不得不将K强制转换为适当的类型,而不是我真正想做的.

      The problem is that when I implement this I get and would have to cast K to the appropriate type, not really what I want to do.

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

      我在做什么错了?

      实际上,使用这样的Observable效果更好,但是我仍然需要在两个不同的地方指定正确的EventType.

      Actually it works better with an Observable like this, 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);
      }
      

      推荐答案

      您不需要参数化观察者,但是需要参数化事件.

      You do not need to parametrise the Observers, but you need to parametrize the events.

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

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

      Then you can have different interface of it for example:

      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方法对观察者不公开(我将在以后看到),我将其分为两个接口:

      on the other hand you need your Observable interface, i have splitted it in two interface in order ti make the notifyObservers method not public to the observers (you will 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();
      }
      

      如果一个主题中将有多个可观察对象,则不能将Observalbe接口直接指向您的主题,因此您需要一个单独的实现类:

      If you would have several observables in a subject, you can not implemnt the Observalbe interface direct to your subject, so you need a seperate 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 subject:

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

      这篇关于无法使观察者模式正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆