|
Evaluating Software Design Patterns — the "Gang of Four" patterns implemented in Java 6 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object dk.rode.thesis.chainofresponsibility.AbstractHandlerChain<R> dk.rode.thesis.chainofresponsibility.WeakHandlerChain<R>
R
- The type of requests handled by this chain.public class WeakHandlerChain<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.
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 |
---|
private final LinkedHashSet<WeakReferenceEntry<Handler<R>>> handlers
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 |
---|
public WeakHandlerChain()
Method Detail |
---|
public List<Handler<R>> getHandlers(Handler<R> handler)
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.
handler
- The handler to start from; can be null.
handler
; never null, but can be empty.public boolean isRegistered(Handler<R> handler)
HandlerChain
handler
is registered to this handler
chain, false if not.
handler
- The handler to test; cannot be null.
public void register(Handler<R> handler)
HandlerChain
handler
supplied
as handler
to this handler chain. Registering the same handler twice is an error.
handler
- The handler to add; cannot be null.HandlerChain.unregister(Handler)
public int size()
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.
public void unregister(Handler<R> handler)
HandlerChain
handler
supplied
as handler
from this handler chain. Trying to remove a handler that is not associated with this handler chain is an error.
handler
- The handler to remove; cannot be null.HandlerChain.register(Handler)
|
Gunni Rode / rode.dk | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |