Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callback/Command vs EventListener/Observer Pattern

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.

like image 939
DD. Avatar asked Jan 21 '12 06:01

DD.


People also ask

What is callback in Observer pattern?

callback - notifies a single caller that some operation finished with some result. observer - notifies zero to n interested parties that some event (for example a finished operation) happened.

Is callback a design pattern?

A good pattern description is the Service Callback design pattern. It's part of a catalog of SOA patterns, but the pattern as described can be employed with generic components that are not SOA services.

Is event listener an observer pattern?

In Listener Design Pattern, when a event happens, the event raiser notifies a global mediator (the singleton Events. instance ), because it has no information about the event handlers. While in Observer Pattern, when any change happens, the observed subject directly notifies all the observers.

When should Observer Pattern be used?

Observer Pattern is one of the behavioral design pattern. Observer design pattern is useful when you are interested in the state of an object and want to get notified whenever there is any change.


2 Answers

Command, callback and observer patterns have different semantics:

  • callback - notifies a single caller that some operation finished with some result
  • observer - notifies zero to n interested parties that some event (for example a finished operation) happened
  • command - encapsulates a operation call in an object thus making it transferable over a wire or persist-able

In your example you could combine both callback and observer patterns to achieve greater API flexibility:

  1. Use the callback pattern to trigger operations and notify the caller asynchronously that the triggered operation finished.
  2. Use the event/observer pattern to give some other components (that did not trigger the operation) the chance to be notified when an operation finishes.
like image 139
saintedlama Avatar answered Oct 10 '22 16:10

saintedlama


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:

  • client starts async task and forgets about it
  • multiple handlers receives notifications when task is completed

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:

  • start async task
  • do something when it is completed

or

  • start async task
  • do something
  • wait till it is completed and do something

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 of Future.

public interface Worker<T> {      Future<T> doAsync();  } 

And Worker can be used following way:

Future<Integer> future = worker.doAsync();  // some work here  Integer result = future.get(); // waits till async work is done 

Future could be a standard java Future. But I'd suggest you to use ListenableFuture from guava library.

like image 35
Mairbek Khadikov Avatar answered Oct 10 '22 16:10

Mairbek Khadikov