一个可观察的多个可观察事件

发布于 2024-11-19 03:36:41 字数 738 浏览 3 评论 0原文

我试图解决在解释一个可观察对象的 update() 调用时所涉及的丑陋的条件转换,该可观察对象想要通知其观察者多种类型的事件。另外,我不想将标志传递给 notifyObservers()/update() 方法。

我不希望观察者必须轮询可观察对象来找出发生了什么变化,我希望通过 update() 方法(或类似方法)将这些新数据提供给观察者。

我有一个解决方案的想法。我为每种类型的通知实例化一个可观察对象。例如: observable 是一个代表硬件设备的对象,它将包含代表其状态的 observables:

public final Observable connectionState = new Observable();
public final Observable dataState = new Observable ();

这样,观察者不需要做任何类型的查询或条件转换,作为一个观察者,即一个重写的 update() 方法可以按通知类型使用。

经过多次挫折后,这是我能想到的最优雅的解决方案,但是我有一种可怕的感觉,我错过了如何正确使用观察者/可观察对象的要点。

我对该解决方案的主要问题是:

  1. 它仍然涉及强制转换(至少它不是有条件的)
  2. 由于可观察量需要可观察,因此它们必须是公共成员。虽然这确实允许观察者调用 addObservable(),但也允许他们调用 notifyObservers()。

我做的事正确吗?

谢谢

I'm trying to get around the ugly conditional casting involved when interpreting an update() call for an observable that will want to notify its observers of multiple types of events. Also, I'd prefer not to pass flags to the notifyObservers()/update() method.

I do not want the observers to have to poll the observable object to find out what's changed, I'd like this new data to be given to the observers via the update() method (or similar.)

I have an idea for a solution. I instanciate one observable object for each type of notification. For example: The observable is an object representing a hardware device, it will contain observables representing its state:

public final Observable connectionState = new Observable();
public final Observable dataState = new Observable ();

This way, observers don't need to do any sort of querying or conditional casting, as one observer, i.e. one overridden update() method can be used per notification type.

After much frustration this is the most elegant solution I can think of, however I have this horrible feeling that I've missed the point about how to use Observers/Observables properly.

My main issues with that solution are:

  1. It still involves a cast (at least it's not conditional)
  2. Since the observables need to be observable, they must be public members. While this does allow observers to call addObservable(), it also allows them to call notifyObservers().

Am I doing the right thing?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小嗷兮 2024-11-26 03:36:41

您正在努力应对观察者模式的 Java 1.0 实现的限制。看看这个问题的这个答案 java.util.Observable 是否在任何地方使用?

它们没有被使用,因为它们
设计有缺陷:它们不是类型
安全的。您可以附加任何对象
对任何 Observable 实现 Observer,
这可能会导致细微的错误
线。

将它们包装在类型安全中
接口数量大约相同
工作作为实施模式
从头开始,所以我猜后者是
在大多数情况下是首选。

也许您应该实现您自己的更适合您需求的模式版本,而不是尝试将您的需求硬塞到 java.util.Observer 中。

You are struggling with the limitations of the Java 1.0 implementation of the Observer pattern. Take a look at this answer to the question Is java.util.Observable used anywhere?

They are not used, because their
design is flawed: they are not type
safe. You can attach any object that
implements Observer to any Observable,
which can result in subtle bugs down
the line.

Wrapping them inside a type safe
interface is about the same amount of
work as implementing the pattern from
scratch, so I guess the latter is
preferred in most cases.

Rather than trying to shoehorn your requirements into java.util.Observer, maybe you should just implement your own version of the pattern that better fits your needs.

以歌曲疗慰 2024-11-26 03:36:41

您可以尝试将 Observable 与 Visitor 模式配对使用:

class MyObserver implements Observer, EventVisitor {
    public void update(Observable o, Object arg) {
        ((EventAcceptor) arg).accept(this);
    }

    public void visit(SomeEvent v) {
        System.out.println("SomeEvent: " + v.s);
    }

    public void visit(AnotherEvent v) {
        System.out.println("AnotherEvent: " + v.info);
    }
}

interface EventVisitor {
    void visit(SomeEvent v);
    void visit(AnotherEvent v);
}

interface EventAcceptor {
    void accept(EventVisitor v);
}

class SomeEvent implements EventAcceptor {
    public final String s;

    public SomeEvent(String s) {
        this.s = s;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class AnotherEvent implements EventAcceptor {
    public final String info;

    public AnotherEvent(String info) {
        this.info = info;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class MyObservable extends Observable {
    void handleSomeEvent() {
        setChanged();
        notifyObservers(new SomeEvent("some event"));
    }

    void handleAnotherEvent() {
        setChanged();
        notifyObservers(new AnotherEvent("some event"));
    }
}

class Sample {
      public static void main(String[] args) {
          MyObservable observable = new MyObservable();
          observable.addObserver(new MyObserver());
          observable.handleSomeEvent();
          observable.handleAnotherEvent();
      }
}

You can try to use Observable paired together with Visitor pattern:

class MyObserver implements Observer, EventVisitor {
    public void update(Observable o, Object arg) {
        ((EventAcceptor) arg).accept(this);
    }

    public void visit(SomeEvent v) {
        System.out.println("SomeEvent: " + v.s);
    }

    public void visit(AnotherEvent v) {
        System.out.println("AnotherEvent: " + v.info);
    }
}

interface EventVisitor {
    void visit(SomeEvent v);
    void visit(AnotherEvent v);
}

interface EventAcceptor {
    void accept(EventVisitor v);
}

class SomeEvent implements EventAcceptor {
    public final String s;

    public SomeEvent(String s) {
        this.s = s;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class AnotherEvent implements EventAcceptor {
    public final String info;

    public AnotherEvent(String info) {
        this.info = info;
    }

    public void accept(EventVisitor v) {
        v.visit(this);
    }
}

class MyObservable extends Observable {
    void handleSomeEvent() {
        setChanged();
        notifyObservers(new SomeEvent("some event"));
    }

    void handleAnotherEvent() {
        setChanged();
        notifyObservers(new AnotherEvent("some event"));
    }
}

class Sample {
      public static void main(String[] args) {
          MyObservable observable = new MyObservable();
          observable.addObserver(new MyObserver());
          observable.handleSomeEvent();
          observable.handleAnotherEvent();
      }
}
ㄖ落Θ余辉 2024-11-26 03:36:41

您的问题有很多可能的解决方案。如果您觉得 Observable 类不适合您的问题,您可以维护自己的侦听器集合。

interface Listener {
    void onEvent1(Type1 arg);
    void onEvent2(Type2 t2, Type3 t3);
    void onEvent3();
}

List<Listener> listeners = new CopyOnWriteArray<Listener>();

public void addListener(Listener l) { listeners.add(l); }

public void onEvent1(Type1 arg) {
     for(Listener l: listeners) l.onEvent1(arg);
}

There are lots of possible solutions for your problem. If you feel the Observable class isn't suited to your problem you can maintain your own collection of listeners.

interface Listener {
    void onEvent1(Type1 arg);
    void onEvent2(Type2 t2, Type3 t3);
    void onEvent3();
}

List<Listener> listeners = new CopyOnWriteArray<Listener>();

public void addListener(Listener l) { listeners.add(l); }

public void onEvent1(Type1 arg) {
     for(Listener l: listeners) l.onEvent1(arg);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文