为了账号安全,请及时绑定邮箱和手机立即绑定

Java 观察者模式或发布者-订阅者模式的变体

Java 观察者模式或发布者-订阅者模式的变体

慕标5832272 2023-02-23 09:54:44
以下 2 个变体的实际观察者模式是什么。在第一个中,Observer 负责订阅。但在第二种情况下,发布者负责将特定观察者添加到订阅者列表中。因为,网络中有一些实现,将它们都作为 java 中的观察者模式。    // Observer is taking the responsibility of subscribing      // Observer.java     @Override     public void subscribe(MessagePublisher publisher) {         publisher.getObservers().add(this);     }2.    // Publisher is taking the observer to subscribe     // Publisher.java      @Override      public void addObserver(Observer observer) {        observers.add(observer);      }
查看完整描述

4 回答

?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

第二个例子是实现所谓的观察者模式。(观察者)想要得到关于被观察对象 X(Observable/事件源)中发生的某些事件的通知,对吧?然后你会告诉Observable 通知你。或者换句话说,你开始监听观察者的通知——这就是为什么观察者也被称为监听者。

Observable 并不知道它所有的订阅者。它只通过 egIObserver接口了解监听器,接口定义了实际的通知回调。Observable 只是将观察者添加到容器或集合中。


第一个例子没有意义。observable 调用观察者的方法让他订阅?那个设计流程一定很奇怪。


假设您有一个FileWriter暴露事件的类FileWriter.Completed。您有另一个FileHandler管理所有文件的类。来电。FileHandler_FileWriter.write(filePath, data)


每次写入操作后,FileHandler必须向用户显示一条消息。因此FileWriter被 所使用FileHandler,但不知道谁在调用该write方法。作为FileHandler的众多消费者之一FileWriter.write(string, string),知道FileWriter implements an observable interface called IWriteToFileCompletedEvent and defines the methodFileWriter.subscribeToWriteToFileCompleted(IObserver eventListener)`。


这就是真正的实施在“现实生活”中的样子


// The interface for the publisher or observable of a special event

interface IWriteToFileCompletedEvent {

  void subscribeToWriteToFileCompleted(IWriteToFileCompletedListener observer);

  void unsubscribeToWriteToFileCompleted(IWriteToFileCompletedListener observer);

}


// The interface for the observer of a special event

interface IWriteToFileCompletedListener {

  void notify(string filePathOfCompletedFile);

}


// The observable that exposes a special event

class FileWriter implements IWriteToFileCompletedEvent {

  private List<IWriteToFileCompletedListener> writeToFileCompletedListeners = new ArrayList<>();


  public void subscribeToWriteToFileCompleted(IWriteToFileCompletedListener observer) {

    this.writeToFileCompletedListeners.add(observer);

  }


  public void unsubscribeToWriteToFileCompleted(IWriteToFileCompletedListener observer) {

    this.writeToFileCompletedListeners.remove(observer);

  }


  public void writeToFile(string filePath, string data) {

    // Write data to file

    // Once done notify all listeners of the write completed event

    for (IWriteToFileCompletedListener observer : this.writeToFileCompletedListeners) {

      observer.notify(filePath);

    }

  } 

}


// The observer of a special event

class ContactsHandler implements IWriteToFileCompletedListener {

  private FileWriter fileWriter = new FileWriter();


  public void saveUserContactToFile(string filePath, string userInput) {

    this.fileWriter.subscribeToWriteToFileCompleted(this);

    this.fileWriter.writeToFile(filePath, userInput);

  }


  // Implementation of interface IWriteToFileCompletedListener 

  public void notify(string filePath) {

    this.fileWriter.unsubscribeToWriteToFileCompleted(this);

    this.messageDialog.show("The new contact was successfully saved to " + filePath);

  }

}


// Another observer of a special event

class SettingsHandler implements IWriteToFileCompletedListener {

  private FileWriter fileWriter = new FileWriter();


  public void saveUserSettingsToFile(string filePath, string userSettings) {

    this.fileWriter.subscribeToWriteToFileCompleted(this);

    this.fileWriter.writeToFile(filePath, userSettings);

  }


  // Implementation of interface IWriteToFileCompletedListener 

  public void notify(string filePath) {

    this.fileWriter.unsubscribeToWriteToFileCompleted(this);

    this.messageDialog.show("The new settings were successfully saved to " + filePath);

  }

}

这些类将像这样交互


public void main(strng[] args {

  SettingsHandler settingsHandler = new SettingsHandler();

  ContactsHandler contactsHandler = new ContactsHandler();


  // Imaging this method receives user input fromo the UI:

  string newContact = textBox.gettext();

  this.contactsHandler.saveUserContactToFile("C:\Contacts.txt", newContact);


  // While waiting for the message to show the user adjusted some settings and clicked 'save'

  string changedSettings = getChangedSettings();

  this.settingsHandler.saveUserSettingsToFile("C:\UserSettings.txt", changedSettings);


  // After a while the user sees the messages send from the event listeners.

}

完全不同类型(SettingsHandler和ContactsHandler)但通用基础/接口类型的多个对象订阅了事件源的同一事件。一切都很干净。使用事件源对象的对象实际上订阅/监听。可观察的类,observable,只是通知所有的监听者。没有其他互动。


总结一下:您的解决方案 1 一点也不方便(尽管您可以让它工作)并且会产生丑陋的代码。


解决方案 2实际上遵循描述如何实现事件的模式。此实现已被证明并得到很好的确立,因为它实现了引入事件的目标并生成干净且可读的代码。


查看完整回答
反对 回复 2023-02-23
?
墨色风雨

TA贡献1853条经验 获得超6个赞

观察者是应该注册自己还是让另一个实体来处理这个责任是应用观察者模式时的一个实现决定,而不是模式本身的结构方面。因此,遇到这两种变体也就不足为奇了。

在 GoF 书籍和其他地方记录的模式结构中,Subject有一个Attach(和Detach)方法作为其接口的一部分。这意味着任何引用主题的实体都可以调用Attach并执行此注册。


查看完整回答
反对 回复 2023-02-23
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

我怀疑他们俩都是。他们都必须实现 Observer 接口。



查看完整回答
反对 回复 2023-02-23
?
呼唤远方

TA贡献1856条经验 获得超11个赞

两者都是观察者模式的有效实现,但是除非您明确需要公开观察者列表,否则第二种方法更可取。



查看完整回答
反对 回复 2023-02-23
  • 4 回答
  • 0 关注
  • 108 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信