Java 中的可观察模式实现
Observable pattern implementation in Java
我目前正在使用 Java 的 Observer/Observable 模式,我想知道:
为什么在我们治疗结束时需要 setChanged() method in its current implementation ? I understand that it is here so that we only have to call notifyObservers() 一次。
这样,如果我们愿意,我们可以使用 clearChanged() 回滚任何更改。但是,我们仍然可以在我们自己的实现中进行所有检查,并且只在我们 绝对 想要更新观察者时调用 notifyObservers() 。
我可能遗漏了一些东西,但我不明白他们为什么不那样简化它。有什么想法吗?
目的是将不同的关注点分开。可以在一个地方调用通知观察者,同时跟踪另一个地方发生的变化。也许在某些情况下您不需要这种分离,但 java.util.Observable 实现旨在能够处理复杂的情况,在这种情况下,更改和通知之间不一定具有 1-1 的对应关系。
例如,您可能需要限制您的通知,以避免您的客户端充斥着事件,这些事件不应影响发生时的跟踪更改。下面的示例使用一个工作线程,该线程定期调用通知方法但不知道更改,以及接受更改但不处理通知的其他代码。
import java.util.*;
public class ObservableExample {
public static void main(String[] args) throws Exception {
CountTracker t = new CountTracker();
t.addObserver(new Observer() {
public void update(Observable observable, Object arg) {
System.out.println("observed " + arg);
}
});
t.startNotifying();
for (int i = 0; i < 100; i++) {
Thread.sleep(100L);
t.incrementCount();
}
t.quitNotifying();
System.out.println("done");
}
}
class CountTracker extends Observable {
private int count = 0;
private Thread notificationThread;
public synchronized void incrementCount() {
count++;
setChanged();
}
public synchronized void startNotifying() {
if (notificationThread == null || !notificationThread.isAlive()) {
notificationThread = new Thread(new Runnable() {
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(1000L);
String event = "current value of count is "
+ CountTracker.this.count;
CountTracker.this.notifyObservers(event);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
notificationThread.start();
}
}
public synchronized void quitNotifying() throws InterruptedException {
if (notificationThread == null || !notificationThread.isAlive()) {
return;
}
notificationThread.interrupt();
System.out.println("wait for notification thread to terminate");
notificationThread.join();
}
}
一个与此类似的现实示例是实现进度条,这需要将表示已完成任务的累积输入转换为完成百分比,并决定更新 UI 显示的频率。
还要考虑到您始终可以子类化 java.util.Observable。 JDK 库开发人员不想支持大量的子专业化,因此他们倾向于创建尽可能广泛有用的 类,但是如果你想消除一些冗余你使用它你可以创造你自己的变体。
我目前正在使用 Java 的 Observer/Observable 模式,我想知道: 为什么在我们治疗结束时需要 setChanged() method in its current implementation ? I understand that it is here so that we only have to call notifyObservers() 一次。
这样,如果我们愿意,我们可以使用 clearChanged() 回滚任何更改。但是,我们仍然可以在我们自己的实现中进行所有检查,并且只在我们 绝对 想要更新观察者时调用 notifyObservers() 。
我可能遗漏了一些东西,但我不明白他们为什么不那样简化它。有什么想法吗?
目的是将不同的关注点分开。可以在一个地方调用通知观察者,同时跟踪另一个地方发生的变化。也许在某些情况下您不需要这种分离,但 java.util.Observable 实现旨在能够处理复杂的情况,在这种情况下,更改和通知之间不一定具有 1-1 的对应关系。
例如,您可能需要限制您的通知,以避免您的客户端充斥着事件,这些事件不应影响发生时的跟踪更改。下面的示例使用一个工作线程,该线程定期调用通知方法但不知道更改,以及接受更改但不处理通知的其他代码。
import java.util.*;
public class ObservableExample {
public static void main(String[] args) throws Exception {
CountTracker t = new CountTracker();
t.addObserver(new Observer() {
public void update(Observable observable, Object arg) {
System.out.println("observed " + arg);
}
});
t.startNotifying();
for (int i = 0; i < 100; i++) {
Thread.sleep(100L);
t.incrementCount();
}
t.quitNotifying();
System.out.println("done");
}
}
class CountTracker extends Observable {
private int count = 0;
private Thread notificationThread;
public synchronized void incrementCount() {
count++;
setChanged();
}
public synchronized void startNotifying() {
if (notificationThread == null || !notificationThread.isAlive()) {
notificationThread = new Thread(new Runnable() {
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(1000L);
String event = "current value of count is "
+ CountTracker.this.count;
CountTracker.this.notifyObservers(event);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
notificationThread.start();
}
}
public synchronized void quitNotifying() throws InterruptedException {
if (notificationThread == null || !notificationThread.isAlive()) {
return;
}
notificationThread.interrupt();
System.out.println("wait for notification thread to terminate");
notificationThread.join();
}
}
一个与此类似的现实示例是实现进度条,这需要将表示已完成任务的累积输入转换为完成百分比,并决定更新 UI 显示的频率。
还要考虑到您始终可以子类化 java.util.Observable。 JDK 库开发人员不想支持大量的子专业化,因此他们倾向于创建尽可能广泛有用的 类,但是如果你想消除一些冗余你使用它你可以创造你自己的变体。