回调/命令与EventListener/Observer模式

DD.*_*DD. 30 design-patterns asynchronous callback command-pattern observer-pattern

我正在尝试设计一个异步框架,并想知道人们认为回调模式与观察者模式的优缺点.

Callback pattern:

//example callback
public interface Callback{
    public void notify(MethodResult result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback callback){
     //do work
     callback.notify(result);
  }
}

//example observer pattern
public interface EventListener{
   public void notify(MethodResult result);

}

public class Worker{
  private EventListener listener;
  public registerEventListener(EventListener listener){
   this.listener=listener;
  }
  public void doAsyncWork(){
     //do work
     listener.notify(result);
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用一个似乎使用这两种模式的框架.EventListener模式不是典型模式,因为它没有监听器列表.这可以通过创建CompositeListener来轻松实现,CompositeListener在侦听器的优先级上有自己的语义,以及如何处理事件到每个侦听器的分布,例如为每个侦听器和串行通知生成新线程.(我实际上认为这是一个好主意,因为它是一个很好的关注点分离,并且是对标准观察者/监听器模式的改进).

你何时应该使用它们?

Thxs.

sai*_*ama 31

命令,回调和观察者模式具有不同的语义:

  • 回调 - 通知单个调用者某些操作已完成某些结果
  • 观察者 - 通知零到n个感兴趣的一方发生了某些事件(例如已完成的操作)
  • command - 将操作调用封装在对象中,从而使其可以通过线路传输或持久化

在您的示例中,您可以将回调和观察者模式结合使用,以实现更高的API灵活性:

  1. 使用回调模式触发操作并异步通知调用者触发的操作已完成.
  2. 使用事件/观察者模式为一些其他组件(触发操作)提供操作完成时通知的机会.


Mai*_*kov 23

这两种模式都很棒,可以选择哪种模式取决于您要构建的内容以及框架的使用方式.

如果您正在尝试构建某种具有以下典型工作流程的发布 - 订阅系统:

  • 客户端启动异步任务并忘记它
  • 多个处理程序在任务完成时接收通知

然后Observer模式是你的自然选择.在进行框架时,您还应该考虑使用EventBus模式来实现松散耦合.

如果您只需要一个简单的异步执行,并且使用您的框架的典型流程是:

  • 启动异步任务
  • 完成后做点什么

要么

  • 启动异步任务
  • 做一点事
  • 等到它完成并做一些事情

然后你应该简单地去Callback.

但是为了实现更多可用和干净的API,我建议你摆脱Callback抽象并设计你的工作者代码以返回某种形式Future.

public interface Worker<T> {

    Future<T> doAsync();

}
Run Code Online (Sandbox Code Playgroud)

并且Worker可以使用以下方式:

Future<Integer> future = worker.doAsync();

// some work here

Integer result = future.get(); // waits till async work is done
Run Code Online (Sandbox Code Playgroud)

Future可能是标准的Java Future.但我建议你使用ListenableFuture番石榴库.


Tom*_*Tom 5

我认为回调模式更好,因为它更简单,这意味着它更可预测,并且由于它自己的变异状态而不太可能有bug.运行中的一个示例是GWT处理浏览器/服务器通信的方式.

您可能希望使用泛型:

//example callback
public interface Callback<T> {
    public void notify(T result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback<SomeTypeOrOther> callback){
     //do work
     callback.notify(result);
  }
}
Run Code Online (Sandbox Code Playgroud)