我正在尝试设计一个异步框架,并想知道人们认为回调模式与观察者模式的优缺点。
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);
}
}
我正在使用一个似乎同时使用这两种模式的框架。 EventListener模式不是典型模式,因为它没有监听器列表。这可以通过创建CompositeListener来轻松实现,该CompositeListener在侦听器的优先级上具有其自己的语义,以及如何处理向每个侦听器分发事件,例如,为每个侦听器和串行通知生成一个新线程。 (我实际上认为这是一个好主意,因为它是一个很好的关注点分离,并且是对标准观察者/听众模式的改进)。
有关何时应该使用每种产品的想法?
Thxs。
答案 0 :(得分:30)
命令,回调和观察者模式具有不同的语义:
在您的示例中,您可以将回调和观察者模式结合起来以实现更高的API灵活性:
答案 1 :(得分:23)
这两种模式都很棒,可供选择的模式取决于您要构建的内容以及框架的使用方式。
如果您正在尝试构建某种具有以下典型工作流程的发布 - 订阅系统:
然后Observer
模式是您的自然选择。在进行框架时,您还应该考虑使用EventBus模式来实现松散耦合。
如果您只需要一个简单的异步执行,并且使用您的框架的典型流程是:
或
然后你应该使用简单的Callback
。
但是为了实现更有用和更干净的API,我建议你摆脱Callback
抽象并设计你的工作代码以返回某种Future
。
public interface Worker<T> {
Future<T> doAsync();
}
Worker
可以按照以下方式使用:
Future<Integer> future = worker.doAsync();
// some work here
Integer result = future.get(); // waits till async work is done
Future
可以是标准java Future。但我建议您使用guava库中的ListenableFuture
。
答案 2 :(得分:5)
我认为回调模式更好,因为它更简单,这意味着它更可预测,并且由于它自己的变异状态而不太可能有bug。运行中的一个示例是the way GWT handles browser / server communication。
您可能希望使用泛型:
//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);
}
}
答案 3 :(得分:2)
让我们以“灯和开关”为例,看看观察者模式和命令模式之间的区别。
观察者模式
命令模式
另一方面,命令模式中的操作ON / OFF变为Command 课。
命令类包含可以在其上执行操作的接收器Lamp。
命令模式通常提供一对一关系,但是可以 可以扩展以提供一对多的功能。
命令模式为命令提供了适当的封装。
答案 4 :(得分:0)
除了
之外,这两种模式几乎没有共同的意图可观察模式可以通知多个侦听器。另一方面,命令模式最适合,需要单个回调处理程序。
在命令模式中,很容易实现撤消操作。
干杯!
答案 5 :(得分:0)
在您的特定代码中,Callback和EventListener之间的唯一区别是:
前者更简单,后者更灵活。如果您要创建一个可重用的框架,那么后者更有意义。
命令设计模式是在对象中执行动作所需的所有信息的封装,与通知事件的机制无关。