Guest User

Callback style examples

a guest
Jul 11th, 2012
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * A few examples that illustrate several styles to chain four events/callbacks.
  3.  *
  4.  * This class compiles, but intentionally doesn't execute, because I'm skipping the
  5.  * implementation for the Caller and Bus interfaces.
  6.  *
  7.  * @author Chris Lercher
  8.  */
  9. public class CallbackStyleExamples {
  10.  
  11.   interface Caller {
  12.     public void call(final String arg, final Callback callback);
  13.   }
  14.  
  15.   interface Callback {
  16.     void onSuccess();
  17.   }
  18.  
  19.   enum BusEvent {
  20.     ALICE_SUCCESSFUL_EVENT,
  21.     BOB_SUCCESSFUL_EVENT,
  22.     CHARLIE_SUCCESSFUL_EVENT,
  23.     DAISY_SUCCESSFUL_EVENT,
  24.   }
  25.  
  26.   interface BusEventListener {
  27.     void onEvent(final BusEvent busEvent);
  28.   }
  29.  
  30.   interface Bus {
  31.     void addEventListener(final BusEvent busEvent, final BusEventListener busEventListener);
  32.     void fireEvent(final BusEvent busEvent);
  33.   }
  34.  
  35.   Caller alice;
  36.   Caller bob;
  37.   Caller charlie;
  38.   Caller daisy;
  39.  
  40.   Bus bus;
  41.  
  42.   private CallbackStyleExamples() { // avoid actual instantiation of this test ;)
  43.   }
  44.  
  45.   /**
  46.    * Nested callbacks can be very hard to read if you nest them too deeply.
  47.    */
  48.   public void nestedCallbacksExample() {
  49.    
  50.     alice.call("a", new Callback() {
  51.      
  52.       @Override
  53.       public void onSuccess() {
  54.         bob.call("b", new Callback() {
  55.          
  56.           @Override
  57.           public void onSuccess() {
  58.             charlie.call("c", new Callback() {
  59.              
  60.               @Override
  61.               public void onSuccess() {
  62.                 daisy.call("d", new Callback() {
  63.                  
  64.                   @Override
  65.                   public void onSuccess() {
  66.                     // finished
  67.                   }
  68.                  
  69.                 });
  70.               }
  71.              
  72.             });
  73.           }
  74.          
  75.         });
  76.       }
  77.      
  78.     });
  79.    
  80.   }
  81.  
  82.   /**
  83.    * You can use your IDE to refactor this easily into named callbacks.
  84.    *
  85.    * - Problem: The control flow is not so immediately obvious anymore.
  86.    * - Still, an IDE can help by using "Search References" (Ctrl-G in Eclipse)
  87.    *   or something similar.
  88.    */
  89.   public void namedCallbacksExample() {
  90.    
  91.     final Callback daisyCallback = new Callback() {
  92.      
  93.       @Override
  94.       public void onSuccess() {
  95.         // finished
  96.       }
  97.     };
  98.    
  99.     final Callback charlieCallback = new Callback() {
  100.      
  101.       @Override
  102.       public void onSuccess() {
  103.         daisy.call("d", daisyCallback);
  104.       }
  105.     };
  106.    
  107.     final Callback bobCallback = new Callback() {
  108.      
  109.       @Override
  110.       public void onSuccess() {
  111.         charlie.call("c", charlieCallback);
  112.       }
  113.     };
  114.    
  115.     final Callback aliceCallback = new Callback() {
  116.      
  117.       @Override
  118.       public void onSuccess() {
  119.         bob.call("b", bobCallback);
  120.       }
  121.     };
  122.    
  123.     alice.call("a", aliceCallback);
  124.   }
  125.  
  126.   /**
  127.    * This is how it looks when using an event bus (or Observer/Publish-Subscribe pattern).
  128.    *
  129.    * - Under the right circumstances (when it's very clear what each event means, and
  130.    *   if you don't have too many), this pattern can make things very nice and clear.
  131.    * - But in other cases, it can make the control flow more confusing (and you easily get twice the lines of code).
  132.    * - It's harder to use your IDE to find out about the control flow.
  133.    * - The GWT History mechanism is a very positive example for where to use this technique reasonably.
  134.    */
  135.   public void eventBusExample() {
  136.    
  137.     class FireEventCallback implements Callback {
  138.  
  139.       private final BusEvent eventToFire;
  140.  
  141.       public FireEventCallback(BusEvent eventToFire) {
  142.         this.eventToFire = eventToFire;
  143.       }
  144.      
  145.       @Override
  146.       public void onSuccess() {
  147.         bus.fireEvent(eventToFire);
  148.       }
  149.      
  150.     }
  151.    
  152.     alice.call("a", new FireEventCallback(BusEvent.ALICE_SUCCESSFUL_EVENT));
  153.     bus.addEventListener(BusEvent.ALICE_SUCCESSFUL_EVENT, new BusEventListener() {
  154.      
  155.       @Override
  156.       public void onEvent(BusEvent busEvent) {
  157.         bob.call("b", new FireEventCallback(BusEvent.BOB_SUCCESSFUL_EVENT));
  158.       }
  159.     });
  160.     bus.addEventListener(BusEvent.BOB_SUCCESSFUL_EVENT, new BusEventListener() {
  161.      
  162.       @Override
  163.       public void onEvent(BusEvent busEvent) {
  164.         charlie.call("c", new FireEventCallback(BusEvent.CHARLIE_SUCCESSFUL_EVENT));
  165.       }
  166.     });
  167.     bus.addEventListener(BusEvent.CHARLIE_SUCCESSFUL_EVENT, new BusEventListener() {
  168.      
  169.       @Override
  170.       public void onEvent(BusEvent busEvent) {
  171.         daisy.call("d", new FireEventCallback(BusEvent.DAISY_SUCCESSFUL_EVENT));
  172.       }
  173.     });
  174.    
  175.     bus.addEventListener(BusEvent.DAISY_SUCCESSFUL_EVENT, new BusEventListener() {
  176.      
  177.       @Override
  178.       public void onEvent(final BusEvent busEvent) {
  179.         // finished
  180.       }
  181.     });
  182.   }
  183.  
  184.   /**
  185.    * In my experience, it's often a good idea to "divide and conquer"
  186.    * by mixing nesting and named callbacks.
  187.    *
  188.    * Depending on the situation, two nested callbacks are often still
  189.    * readable, and they reduce jumping around between methods when
  190.    * reading the code by 50%.
  191.    */
  192.   public void mixedExample() {
  193.    
  194.     final Callback charlieCallback = new Callback() {
  195.      
  196.       @Override
  197.       public void onSuccess() {
  198.        
  199.         daisy.call("d", new Callback() {
  200.              
  201.           @Override
  202.           public void onSuccess() {
  203.             // finished
  204.           }
  205.         });
  206.       }
  207.     };
  208.    
  209.     alice.call("a", new Callback() {
  210.      
  211.       @Override
  212.       public void onSuccess() {
  213.        
  214.         bob.call("b", new Callback() {
  215.          
  216.           @Override
  217.           public void onSuccess() {
  218.            
  219.             charlie.call("c", charlieCallback);
  220.           }
  221.         });
  222.       }
  223.     });
  224.   }
  225. }
Advertisement
Add Comment
Please, Sign In to add comment