Advertisement
Guest User

Callback style examples

a guest
Jul 11th, 2012
309
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.     alice.call("a", new Callback() {
  138.      
  139.       @Override
  140.       public void onSuccess() {
  141.         bus.fireEvent(BusEvent.ALICE_SUCCESSFUL_EVENT);
  142.       }
  143.     });
  144.    
  145.     bus.addEventListener(BusEvent.ALICE_SUCCESSFUL_EVENT, new BusEventListener() {
  146.      
  147.       @Override
  148.       public void onEvent(final BusEvent busEvent) {
  149.         bob.call("b", new Callback() {
  150.          
  151.           @Override
  152.           public void onSuccess() {
  153.             bus.fireEvent(BusEvent.BOB_SUCCESSFUL_EVENT);
  154.           }
  155.         });
  156.        
  157.       }
  158.     });
  159.    
  160.     bus.addEventListener(BusEvent.BOB_SUCCESSFUL_EVENT, new BusEventListener() {
  161.      
  162.       @Override
  163.       public void onEvent(final BusEvent busEvent) {
  164.         charlie.call("c", new Callback() {
  165.          
  166.           @Override
  167.           public void onSuccess() {
  168.             bus.fireEvent(BusEvent.CHARLIE_SUCCESSFUL_EVENT);
  169.           }
  170.         });
  171.        
  172.       }
  173.     });
  174.    
  175.     bus.addEventListener(BusEvent.CHARLIE_SUCCESSFUL_EVENT, new BusEventListener() {
  176.      
  177.       @Override
  178.       public void onEvent(final BusEvent busEvent) {
  179.         daisy.call("d", new Callback() {
  180.          
  181.           @Override
  182.           public void onSuccess() {
  183.             bus.fireEvent(BusEvent.DAISY_SUCCESSFUL_EVENT);
  184.           }
  185.         });
  186.        
  187.       }
  188.     });
  189.    
  190.     bus.addEventListener(BusEvent.DAISY_SUCCESSFUL_EVENT, new BusEventListener() {
  191.      
  192.       @Override
  193.       public void onEvent(final BusEvent busEvent) {
  194.         // finished
  195.       }
  196.     });
  197.   }
  198.  
  199.   /**
  200.    * In my experience, it's often a good idea to "divide and conquer"
  201.    * by mixing nesting and named callbacks.
  202.    *
  203.    * Depending on the situation, two nested callbacks are often still
  204.    * readable, and they reduce jumping around between methods when
  205.    * reading the code by 50%.
  206.    */
  207.   public void mixedExample() {
  208.    
  209.     final Callback charlieCallback = new Callback() {
  210.      
  211.       @Override
  212.       public void onSuccess() {
  213.        
  214.         daisy.call("d", new Callback() {
  215.              
  216.           @Override
  217.           public void onSuccess() {
  218.             // finished
  219.           }
  220.         });
  221.       }
  222.     };
  223.    
  224.     alice.call("a", new Callback() {
  225.      
  226.       @Override
  227.       public void onSuccess() {
  228.        
  229.         bob.call("b", new Callback() {
  230.          
  231.           @Override
  232.           public void onSuccess() {
  233.            
  234.             charlie.call("c", charlieCallback);
  235.           }
  236.         });
  237.       }
  238.     });
  239.   }
  240. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement