Java观察者模式或发布者-订阅者模式的变化
下面两种变化的实际观察者模式是什么Java观察者模式或发布者-订阅者模式的变化,java,design-patterns,publish-subscribe,observer-pattern,Java,Design Patterns,Publish Subscribe,Observer Pattern,下面两种变化的实际观察者模式是什么 在第一种情况下,观察员承担以下责任: 订阅 但在第二个场景中,Publisher采用 将特定观察员添加到订户列表的责任 因为,在web上有一些实现,它们都是java中的观察者模式 1. //观察员负责订阅 //Observer.java @凌驾 public-void-subscribe(MessagePublisher-publisher){ publisher.getobsers().add(此); } 二, //Publisher正在让观察员订阅 //
//观察员负责订阅
//Observer.java
@凌驾
public-void-subscribe(MessagePublisher-publisher){
publisher.getobsers().add(此);
}
二,
//Publisher正在让观察员订阅
//Publisher.java
@凌驾
公共观察者(观察者){
添加观察员(观察员);
}
我怀疑他们俩都是。它们都必须实现Observer接口。第二个示例是实现所谓的Observer模式。你(观察者)想要得到在对象X(可观察者)中发生的事件的通知,对吗?你会告诉被观察者通知你。或者换句话说,你开始听它,这就是为什么它也被称为监听器。可观测对象并不知道它的所有订户。他只是将它们添加到容器或集合中。观察者知道所有观察者实现的接口IObserver
,因此知道调用哪个方法(回调)
第一个例子没有意义。被观察者对观察者调用一个方法使其订阅?这种设计流程一定很奇怪
假设您有一个FileWriter
类,它公开一个事件FileWriter.Completed
。您还有另一个类FileHandler
,它管理所有文件。FileHandler
调用FileWriter.write(filePath,data)
。每次操作后,FileHandler
希望向用户显示一条消息。因此,FileHandler使用“FileWriter”,但不知道是谁在调用write方法。FileHandler是
FileWriter.write(string,string)的众多使用者之一,它知道
FileWriter实现了一个可观察的接口,名为IWriteToFileCompletedEvent
。这就是为什么他可以确保可观察对象具有方法FileWriter.subscribeToWriteToFileCompleted(IObserver eventListener)
。您希望FileWriter
在订阅之前如何了解其活动的所有消费者?。想想看。这可能是一些奇怪的API,比如:FileWriter.write(filepath,data,This)
为FileWriter
提供对侦听器的引用。然后,FileWriter
接受侦听器引用并调用listener.subscribe(this)
。现在,FileHandler
(监听器)对FileWriter
有一个无用的引用(因为他以前知道FileWriter
,因为他在上面调用了FileWriter.write
),所以监听器接受了他已经不得不调用的observable.getobservates().add(这个)
。我打字时中风了。说真的,这是一些疯狂的意大利面条
这就是“现实生活”中实际实现的样子。
// 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);
}
}
多个类型完全不同的对象(SettingsHandler
和ContactsHandler
)订阅了同一事件。一切都很干净。使用他想要观察的对象的对象订阅。可观察的类,即可观察的类,只是通知所有订阅者。就这样
总而言之:您的解决方案1一点也不方便(尽管您可以让它工作),并且会产生难看的代码
解决方案2实际上遵循描述如何实现事件的模式。此实现已被证明并得到了很好的验证,因为它实现了引入事件的目标,并生成了清晰可读的代码。在应用观察者模式时,观察者是否应该注册自己或让另一个实体处理此职责是一个实现决策,而不是模式本身的结构方面。因此,遇到这两种变体并不奇怪
在GoF书籍和其他地方记录的模式结构中,主题
有一个附加
(和分离
)方法作为其接口的一部分。这意味着任何引用主题的实体都可以调用Attach
并执行此注册。这两种方法都是观察者模式的有效实现,但是除非您明确需要公开观察者列表,否则第二种方法更可取。就我个人而言,我会通过(1)实现这两种方法do:publisher.addObserver(此)代码>。我要说的是,拥有(1)as是不正确的,因为它是基于公开发布者内部数据结构的功能。例如,如果Publisher决定更改为另一个数据结构,或者想记录新的观察者,该怎么办?是的。我明白你的意思。非常感谢。
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.
}