java - Java中的可观察模式实现

标签 java design-patterns observer-pattern

我目前正在使用 Java 的 Observer/Observable 模式,我想知道: 为什么需要 setChanged()当前实现中的方法?我知道它在这里,所以我们只需要调用 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 - Java中的可观察模式实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31589711/

相关文章:

java - 线程中出现异常,java代码将无法正常执行。 if/else 语句

android - Live Data Observer 只调用了一次。当再次调用 api 更新 UI 时,它不会从服务器更新数据

java - 如何将观察者模式与 jms 接收器一起应用

c++ - 相互了解的对象集合

java - 除了依赖注入(inject)或观察者之外,Java 中单例模式的替代方案

Java 枚举与字符串常量

Java:无法将字符串转换为数组

java - 如何让servlet容器(Tomcat)中断/销毁servlet请求?

c# - 如何在C#中自动生成装饰器模式

java - 策略设计模式(带参数方法)- JAVA