I'm trying to design an async framework and wanted to know what people think are the pros/cons of the callback pattern vs the 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);
}
}
I'm working with a framework which seems to use both of these patterns. The EventListener pattern is not the typical pattern as it doesn't have a list of listeners. This can easily be implemented though by creating a CompositeListener which has its own semantics on the priority of listeners and how to handle the distribution of events to each listener e.g. spawning a new thread for each listener vs serial notifications. (I actually think this is a good idea as its a good separation of concerns and is an improvement on the standard observer/listener pattern).
Any thoughts on when you should use each?
Thxs.
Both patterns are great and which one to choose depends on what are you going to build and how your framework will be used.
If you are trying to build some kind of publish-subscribe system with following typical flow of work:
then
Observer
pattern is a natural choice for you. As you are doing a framework you should also consider using EventBus pattern to achieve loose coupling.If you need nothing more than a simple asynchronous execution and a typical flow using of your framework is:
or
then you should go with simple
Callback
.But in order to achieve more usable and clean API I'd recommend you to get rid of
Callback
abstraction and design your worker code to return a some kind ofFuture
.And
Worker
can be used following way:Future
could be a standard java Future. But I'd suggest you to useListenableFuture
from guava library.Command, callback and observer patterns have different semantics:
In your example you could combine both callback and observer patterns to achieve greater API flexibility:
Both patterns share few common intentions except,
Observable pattern can notify multiple listeners. On the other hand, command pattern will be best suited, where you need single callback handler.
In command pattern, it's easy to implement the undo operation.
Cheers!
I'd argue that the callback pattern is better as it is simpler which means it'll be more predictable and less likely to have bugs due to it's own mutating state. An example of this in operation would be the way GWT handles browser / server communication.
You might want to use generics though: