【问题标题】:Observer pattern with a filter, at what level to filter?带有过滤器的观察者模式,在什么级别进行过滤?
【发布时间】:2017-01-05 19:19:09
【问题描述】:

假设我有一个班级广播员来广播某些事件。 例如:

List<Observers> observers = …

Public void broadcast(Event e) {
    for (each observer: observers) {
       observer.observe(e);
   }
}

然后我有一个名为 EventReceiver 的类,它执行以下操作

public void processEvent(Event e) {
    saveToDatabase(e);
    broadcast(e);
}

现在:一个新的需求来了,当Event是“foo”类型时,我们应该把它保存到数据库而不是广播它。

我应该在哪一层过滤?在 broadcast.java 或 EventReceiver.java 中?

例如:

Public void broadcast(Event e) {
If (event != foo) {
    for (each observer: observers) {
       observer.observe(e);
   }
 }
}

或者

public void processEvent(Event e) {
    saveToDatabase(e);
   If (event != foo) {
        broadcast(e);
   }
}

【问题讨论】:

    标签: java design-patterns observer-pattern


    【解决方案1】:

    我会说processEvent,您的第二个样本。在您决定广播它之前,过滤的责任应该来自首先处理事件的代码主体。将事件传递给broadcast 是没有意义的,它不会或不应该被广播。

    【讨论】:

      【解决方案2】:

      如果您有 2 个观察者,一个广播,另一个写入 DB,那么您可以使用装饰器模式进行过滤。

      class Broadcaster implements Observer {
          public void process(Event e) {
              broadcast(e);
          }
      }
      
      
      class DbWriter implements Observer {
          public void process(Event e) {
              writeToDb(e);
          }
      }
      
      
      
      class FilterOutFoo implements Observer {
          private Observer decorated;
      
          public Filter(Observer decorated) {
              this.decorated = decorated;
          }
      
          public void process(Event e) {
              if (!e.isFoo())
                  decorated.processs(e);
          }
      }
      
      observed.addObserver(new Broadcaster());
      observed.addObserver(new FilterOutFoo(new DbWriter()));
      

      【讨论】:

      • 你能详细说明一下吗?
      【解决方案3】:

      过滤器应该在 EventReceiver.java 中明确实现,因为您可以稍后升级 Broadcast.java 类来广播其他事件。

      您可以有许多接收器,每个接收器都根据用例实现自己的过滤器。

      此外,正如Michael 指出的那样,广播一个不会被广播的事件是没有意义的。

      这就像将手机信号塔静音而不是手机本身静音。你永远不会接到任何电话。但是,如果您改为将手机静音,则您决定何时取消静音。 (对不起,比较:))

      【讨论】:

        【解决方案4】:

        不要过滤。子类。如果有 Foo 类型的事件,那么应该有一个类 FooEvent。让观察者注册FooEvent通知,让观察者只收到他们关心的通知。

        问题的根源在于代表多种事件类型的单个Event 类。相反,每个事件类型都应该有自己的类和自己的观察者列表。

        【讨论】:

          猜你喜欢
          • 2023-03-20
          • 2020-09-05
          • 1970-01-01
          • 1970-01-01
          • 2016-11-19
          • 1970-01-01
          • 2021-03-06
          • 2019-05-01
          • 2019-02-11
          相关资源
          最近更新 更多