Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

dk.rode.thesis.chainofresponsibility
Class WeakHandlerChain<R>

java.lang.Object
  extended by dk.rode.thesis.chainofresponsibility.AbstractHandlerChain<R>
      extended by dk.rode.thesis.chainofresponsibility.WeakHandlerChain<R>
Type Parameters:
R - The type of requests handled by this chain.
All Implemented Interfaces:
Handler<R>, HandlerChain<R>, HandlerLink<R>

public class WeakHandlerChain<R>
extends AbstractHandlerChain<R>

A weak handler chain is a thread-safe handler chain storing registered handlers as weak references.

Handler chains can change at runtime, and handlers are internally stored as weak references. Hence, registering a handler to a chain will not increase its reference count, and they may be garbage collected at any time. The chain automatically purges handlers that have been garbage collected.

A handler chain is thread safe.

Author:
Gunni Rode / rode.dk
See Also:
StandardHandlerChain

Field Summary
private  LinkedHashSet<WeakReferenceEntry<Handler<R>>> handlers
          The ordered list of handlers, where the first handler is the first inserted element.
 
Constructor Summary
WeakHandlerChain()
          No-arg constructor.
 
Method Summary
 List<Handler<R>> getHandlers(Handler<R> handler)
          Returns an ordered list of the handlers currently associated with this chain, starting from the handler after handler, if supplied.
 boolean isRegistered(Handler<R> handler)
          Returns true if handler is registered to this handler chain, false if not.
 void register(Handler<R> handler)
          Registers the handler supplied as handler to this handler chain.
 int size()
          Return the size of this handler chain.
 void unregister(Handler<R> handler)
          Removes the handler supplied as handler from this handler chain.
 
Methods inherited from class dk.rode.thesis.chainofresponsibility.AbstractHandlerChain
forward, handle, handle, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

handlers

private final LinkedHashSet<WeakReferenceEntry<Handler<R>>> handlers
The ordered list of handlers, where the first handler is the first inserted element.

We use weak references to ensure that when a handler goes out off scope, it does not need to explicitly invoke unregister(Handler) (though it may).

Implementation notes:
For small chains, a simple list will suffice, but it does not scale well: if each handler starting from handler m in the chain reinvokes the chain, we get a running time of O(n*m), i.e. worst time O(n*n), where n is the chain length. Existence, registration, and unregistration takes O(n), but can at the same time discard garbage collected handlers.

A better solution is to use a linked hash set to avoid O(n) existence, registration, and unregistration time, and only purge garbage collected entries when a list is retrieved. But, since weak references are used, this require a mapping class because weak references use the identity (==) operator to test for equality. This is the implementation here.

An even faster and more scalable solution would be to use an index into a list, pointing to the start of the sub-list to return. A navigable map (tree map) can be used for this, i.e. tailMap(..) methods, but since we do not enforce comparable handlers and use weak references, this is actually quite tricky! For this simple example, we are satisfied with our simple solution.

Never null.

Constructor Detail

WeakHandlerChain

public WeakHandlerChain()
No-arg constructor.

Method Detail

getHandlers

public List<Handler<R>> getHandlers(Handler<R> handler)
Returns an ordered list of the handlers currently associated with this chain, starting from the handler after handler, if supplied.

If handler is null, the entire list of handlers is returned. If handler is not registered to this chain, the entire list of handlers is returned.

Modifying the returned list will not affect this chain.

This method will purge handlers that have been garbage collected because no longer referenced.

Parameters:
handler - The handler to start from; can be null.
Returns:
The ordered list of handlers, starting after handler; never null, but can be empty.

isRegistered

public boolean isRegistered(Handler<R> handler)
Description copied from interface: HandlerChain
Returns true if handler is registered to this handler chain, false if not.

Parameters:
handler - The handler to test; cannot be null.
Returns:
True if registered, false if not.

register

public void register(Handler<R> handler)
Description copied from interface: HandlerChain
Registers the handler supplied as handler to this handler chain.

Registering the same handler twice is an error.

Parameters:
handler - The handler to add; cannot be null.
See Also:
HandlerChain.unregister(Handler)

size

public int size()
Return the size of this handler chain.

In case contained handlers have been garbage collection since the last call to getHandlers(Handler), the returned size will be larger than the actual size.

Returns:
The size.

unregister

public void unregister(Handler<R> handler)
Description copied from interface: HandlerChain
Removes the handler supplied as handler from this handler chain.

Trying to remove a handler that is not associated with this handler chain is an error.

Parameters:
handler - The handler to remove; cannot be null.
See Also:
HandlerChain.register(Handler)

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.