1.5.2. Chain of Responsibility Sample Code

From the book:

This pattern is useful when we have code of the form shown in Listing 1.3.

Listing 1.3: Nested if-else-if constructs.

//:~ core/src/main/.../ch01/ChainDemo.java
public void handleWithoutChain(
    String key, Consumer<String> processor) {
  var item = map1.get(key);
  if (item != null) processor.accept(item);
  else {
    item = map2.get(key);
    if (item != null) processor.accept(item);
    else {
      item = map3.get(key); // ad nauseum
    }
  }
}

Instead of the multiconditional if-else statement, we create an abstract Handler class. The default implementation of handle() is to pass the call down the chain to the next handler.

Listing 1.4: Chain-of-responsibility handler.

//:~ core/src/main/.../ch01/Handler.java
public abstract class Handler {
  private final Handler next;
  public Handler(Handler next) {
    this.next = next;
  }
  public void handle(String key, Consumer<String> processor) {
    if (next != null) next.handle(key, processor);
  }
}

Our MapHandler contains the implementation that calls process(item) if the item is found in our map; else it calls super.handle(key).

Listing 1.5: Concrete handler for maps.

//:~ core/src/main/.../ch01/MapHandler.java
public class MapHandler extends Handler {
  private final Map<String, String> map;
  public MapHandler(Map<String, String> map, Handler next) {
    super(next);
    this.map = map;
  }
  @Override
  public void handle(String key, Consumer<String> processor) {
    String item = map.get(key);
    if (item != null) processor.accept(item);
    else super.handle(key, processor);
  }
}

Inside our class, we would set up the chain as we see in Listing 1.6.

Listing 1.6: Chain of handlers as field.

//:~ core/src/main/.../ch01/ChainDemo.java
private final Handler chain =
    new MapHandler(map1,
        new MapHandler(map2,
            new MapHandler(map3, null)));

Instead of the complicated if-else-if construct from Listing 1.3, we can write:

Listing 1.7: Using the chain-of-responsibility handler.

//:~ core/src/main/.../ch01/ChainDemo.java
private void handleWithChain(
    String key, Consumer<String> processor) {
  chain.handle(key, processor);
}

Discussion

0 comments