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
命令,回调和观察者模式具有不同的语义:
在您的示例中,您可以将回调和观察者模式结合使用,以实现更高的API灵活性:
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番石榴库.
我认为回调模式更好,因为它更简单,这意味着它更可预测,并且由于它自己的变异状态而不太可能有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)