【问题标题】:Observable pattern implementation in JavaJava中的可观察模式实现
【发布时间】:2015-07-23 14:03:04
【问题描述】:

我目前正在使用 Java 的观察者/可观察模式,我想知道: 为什么在当前实现中需要setChanged() 方法?我知道它就在这里,所以我们只需要在治疗结束时致电notifyObservers() 一次。

这样,如果我们愿意,我们可以使用 clearChanged() 回滚任何更改。但是,我们仍然可以在我们自己的实现中进行所有检查,并且仅在我们绝对想要更新观察者时调用 notifyObservers()。

我可能遗漏了一些东西,但我不明白他们为什么不那样简化它。有什么想法吗?

【问题讨论】:

  • 您问他们为什么不假设您的实现将具有某些功能,而是提供了实现所需的所有工具?
  • @dave-newton 好吧,这么说,这个问题似乎很愚蠢,当然。但是,不管你怎么做,你仍然需要检查你是否调用了 clearChanged() 。那么,为什么不满足于每次 notifyObservers() 的更新,而不是使用(看似多余的) setChanged() 标志?
  • 因为您可能会在各处进行更改,但只是偶尔通知观察者?例如,在一些复杂的业务逻辑结束时,可能会或可能不会在整个多步骤流程中调用setChanged():当它完成时,只有在任何业务逻辑步骤期间它发生了变化时,你才notifyObservers()。这样,您唯一需要做的“更改跟踪”就是致电setChanged() 并在最后检查。

标签: java design-patterns observer-pattern


【解决方案1】:

其目的是将单独的关注点分开。可以在一个地方调用通知观察者,同时在另一个地方跟踪发生的变化。也许在某些情况下您不需要这种分离,但 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 库开发人员不想支持大量的子专业化,因此他们倾向于创建尽可能广泛有用的类,但如果您想消除使用方式的一些冗余,您可以创建自己的变化。

【讨论】:

    猜你喜欢
    • 2019-09-17
    • 2012-09-02
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多