第二个例子是实现所谓的观察者模式。 (观察者)想要得到关于观察对象 X(观察者/事件源)中发生的某些事件的通知,对吗?然后你会告诉 Observable 通知你。或者换句话说,你开始监听观察者的通知——这就是为什么观察者也被称为监听者。
Observable 并不知道它的所有订阅者。它只知道监听器,例如IObserver 接口,它定义了实际的通知回调。 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 IWriteToFileCompletedEventand 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 实际上遵循描述如何实现事件的模式。这个实现已经被证明并且被很好地确立,因为它实现了引入事件的目标并且产生了干净和可读的代码。