Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * A few examples that illustrate several styles to chain four events/callbacks.
- *
- * This class compiles, but intentionally doesn't execute, because I'm skipping the
- * implementation for the Caller and Bus interfaces.
- *
- * @author Chris Lercher
- */
- public class CallbackStyleExamples {
- interface Caller {
- public void call(final String arg, final Callback callback);
- }
- interface Callback {
- void onSuccess();
- }
- enum BusEvent {
- ALICE_SUCCESSFUL_EVENT,
- BOB_SUCCESSFUL_EVENT,
- CHARLIE_SUCCESSFUL_EVENT,
- DAISY_SUCCESSFUL_EVENT,
- }
- interface BusEventListener {
- void onEvent(final BusEvent busEvent);
- }
- interface Bus {
- void addEventListener(final BusEvent busEvent, final BusEventListener busEventListener);
- void fireEvent(final BusEvent busEvent);
- }
- Caller alice;
- Caller bob;
- Caller charlie;
- Caller daisy;
- Bus bus;
- private CallbackStyleExamples() { // avoid actual instantiation of this test ;)
- }
- /**
- * Nested callbacks can be very hard to read if you nest them too deeply.
- */
- public void nestedCallbacksExample() {
- alice.call("a", new Callback() {
- @Override
- public void onSuccess() {
- bob.call("b", new Callback() {
- @Override
- public void onSuccess() {
- charlie.call("c", new Callback() {
- @Override
- public void onSuccess() {
- daisy.call("d", new Callback() {
- @Override
- public void onSuccess() {
- // finished
- }
- });
- }
- });
- }
- });
- }
- });
- }
- /**
- * You can use your IDE to refactor this easily into named callbacks.
- *
- * - Problem: The control flow is not so immediately obvious anymore.
- * - Still, an IDE can help by using "Search References" (Ctrl-G in Eclipse)
- * or something similar.
- */
- public void namedCallbacksExample() {
- final Callback daisyCallback = new Callback() {
- @Override
- public void onSuccess() {
- // finished
- }
- };
- final Callback charlieCallback = new Callback() {
- @Override
- public void onSuccess() {
- daisy.call("d", daisyCallback);
- }
- };
- final Callback bobCallback = new Callback() {
- @Override
- public void onSuccess() {
- charlie.call("c", charlieCallback);
- }
- };
- final Callback aliceCallback = new Callback() {
- @Override
- public void onSuccess() {
- bob.call("b", bobCallback);
- }
- };
- alice.call("a", aliceCallback);
- }
- /**
- * This is how it looks when using an event bus (or Observer/Publish-Subscribe pattern).
- *
- * - Under the right circumstances (when it's very clear what each event means, and
- * if you don't have too many), this pattern can make things very nice and clear.
- * - But in other cases, it can make the control flow more confusing (and you easily get twice the lines of code).
- * - It's harder to use your IDE to find out about the control flow.
- * - The GWT History mechanism is a very positive example for where to use this technique reasonably.
- */
- public void eventBusExample() {
- alice.call("a", new Callback() {
- @Override
- public void onSuccess() {
- bus.fireEvent(BusEvent.ALICE_SUCCESSFUL_EVENT);
- }
- });
- bus.addEventListener(BusEvent.ALICE_SUCCESSFUL_EVENT, new BusEventListener() {
- @Override
- public void onEvent(final BusEvent busEvent) {
- bob.call("b", new Callback() {
- @Override
- public void onSuccess() {
- bus.fireEvent(BusEvent.BOB_SUCCESSFUL_EVENT);
- }
- });
- }
- });
- bus.addEventListener(BusEvent.BOB_SUCCESSFUL_EVENT, new BusEventListener() {
- @Override
- public void onEvent(final BusEvent busEvent) {
- charlie.call("c", new Callback() {
- @Override
- public void onSuccess() {
- bus.fireEvent(BusEvent.CHARLIE_SUCCESSFUL_EVENT);
- }
- });
- }
- });
- bus.addEventListener(BusEvent.CHARLIE_SUCCESSFUL_EVENT, new BusEventListener() {
- @Override
- public void onEvent(final BusEvent busEvent) {
- daisy.call("d", new Callback() {
- @Override
- public void onSuccess() {
- bus.fireEvent(BusEvent.DAISY_SUCCESSFUL_EVENT);
- }
- });
- }
- });
- bus.addEventListener(BusEvent.DAISY_SUCCESSFUL_EVENT, new BusEventListener() {
- @Override
- public void onEvent(final BusEvent busEvent) {
- // finished
- }
- });
- }
- /**
- * In my experience, it's often a good idea to "divide and conquer"
- * by mixing nesting and named callbacks.
- *
- * Depending on the situation, two nested callbacks are often still
- * readable, and they reduce jumping around between methods when
- * reading the code by 50%.
- */
- public void mixedExample() {
- final Callback charlieCallback = new Callback() {
- @Override
- public void onSuccess() {
- daisy.call("d", new Callback() {
- @Override
- public void onSuccess() {
- // finished
- }
- });
- }
- };
- alice.call("a", new Callback() {
- @Override
- public void onSuccess() {
- bob.call("b", new Callback() {
- @Override
- public void onSuccess() {
- charlie.call("c", charlieCallback);
- }
- });
- }
- });
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement