|
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.observer.ObserverManager
@ParticipantUsage(value="Observer", type=java.lang.reflect.Method.class) @Participant(value={"Subject","ConcreteSubject"}) public class ObserverManager
An observer manager is a stand-alone manager storing
any type of observer that will be notified with methods
declared in its class that are annotated with a matching
Executor
annotation. Registered observers subscribe
to all or nothing. A real subject implementation
can use this manager as a component, delegating the notification
and work to it. The subject, if any, must be supplied as one of
the arguments to the notifyObservers(Object...)
method.
When observers are added
,
the matching methods will be found: methods annotated with
the Executor
annotation declaring a
context
to which the
owner type
of the manager is
assignable to. The methods represent the notification mechanism
for the observer in question and will be executed, using the
observer object as the target if not static, when
notifyObservers(Object...)
is invoked.
The formal parameter types of applicable methods must be
supplied at construction time, and matching arguments
supplied to the notifyObserver
method. The formal
parameter types ignore primitive types, i.e. Integer.class
and Integer.TYPE
can both represent int
,
for example.
Any manager must use an error handler
to determine how errors during notification should be
handled, for example if the notification should continue
in case of errors or stop immediately. For convenience, the
ObserverManager.NotificationPolicy
enumeration defines two such default
error handlers.
The observer manager is not thread-safe! It does not enforce synchronisation, neither when adding or removing observers, nor when observers are notified. It could be potentially dangerous or least time consuming to notify observers from a synchronised context, holding a lock on the manager itself. If synchronisation is required, the context using the manager must enforce it.
Implementation notes:
An observer manager can be seen as a simple version of the
Change Manager object described by Gamma et al. [Gamma95, p.299]
that allows the subject to be supplied as an argument to
the notifyObservers(Object...)
method.
By using annotations and reflection, any method with a matching signature can be used to notify the observer. This includes static and/or private methods if the security manager allows it.
Methods annotated with the Executor
annotation must
declare the applicable context, i.e. classes allowed to use
it. This ensures that different observer registries can
use the same annotation in the same class.
Observers are only stored as weak references, and the manager will not prevent ordinary garbage collection of the observers. Hence, anonymous non-referenced observers are not a good idea for this manager as they will be garbage collected without warning.
As always, reflection can cause numerous runtime errors! Hence, the observer manager utilises error handlers to determine how errors should be processed in case of notification errors.
An alternative to annotations is to use a regular interface to
specify both the observer type and the means (method) to perform the
notification. The Chain of Responsibility
pattern utilises such an approach to identify its handlers
(observers) in the HandlerChain
class.
Executor
Nested Class Summary | |
---|---|
static class |
ObserverManager.NotificationPolicy
Default error handlers for observer registries. |
Field Summary | |
---|---|
private ErrorHandler |
errorHandler
An error handler used to handle errors thrown during notification to a given observer, which will decide if a given type of error will cause the overall notification to fail. |
private Map<Method,List<WeakReference<Object>>> |
observers
The observers registered in this manager. |
private Class<?> |
ownerType
The owner type of this manager. |
private Class<?>[] |
parameterTypes
The formal parameter types declared for all methods to be used to notify registered observers. |
private int |
size
The number of registered observers. |
Constructor Summary | |
---|---|
ObserverManager(Class<?> ownerType,
Class<?>... parameterTypes)
Constructor. |
|
ObserverManager(ErrorHandler errorHandler,
Class<?> ownerType,
Class<?>... parameterTypes)
Constructor. |
|
ObserverManager(ObserverManager manager)
Copy constructor. |
Method Summary | ||
---|---|---|
|
addObserver(Class<? extends T> clazz,
T observer)
Adds the observer supplied as observer to this
manager, associated with the methods annotated in the class
supplied as clazz with a context type
the owner type of this manager is
assignable to, if any. |
|
boolean |
addObserver(Object observer)
Adds the observer supplied as observer to this
manager, associated with the methods annotated in the class
of object with a context type
the owner type of this manager is
assignable to, if any. |
|
Map<Method,List<Object>> |
getObserverMethods()
Returns the observers and their associated notification methods, regardless if static or not, registered to this manager. |
|
Collection<Object> |
getObservers()
Returns the observers currently associated with this observable sequence. |
|
Class<?> |
getOwnerType()
Returns the owner type of this manager. |
|
boolean |
notifyObservers(Object... arguments)
Notifies all observers stored in this manager, using the arguments for each method supplied as arguments . |
|
private boolean |
remove(Method method,
Object observer)
Removes the specific notification method supplied as method
from the observer supplied as observer . |
|
|
removeObserver(Class<? extends T> clazz,
T observer)
Removes the observer supplied as observer from this
manager. |
|
boolean |
removeObserver(Object observer)
Removes the observer supplied as observer from this
manager. |
|
int |
size()
Return the number of observers associated with this manager. |
|
String |
toString()
Returns the string representation of this manager. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
private final ErrorHandler errorHandler
Default handler is ObserverManager.NotificationPolicy.StopOnError
.
Never null.
private final Map<Method,List<WeakReference<Object>>> observers
Keys are the methods to perform the notification and the associated value a list of observers to be notified using that method, stored as weak references.
Never null, but can be empty.
private final Class<?> ownerType
For an observer to be registered to this manager, this
type must be assignable to the class specified in
Executor.value()
for each annotated
method.
Never null.
private final Class<?>[] parameterTypes
Primitive types are ignored, i.e. the parameter types may
contain both Integer.class
and Integer.TYPE
to represent an int
.
Never null, but can be empty.
private int size
A given observer may be included more than once if it is notified with more than one annotated method.
Constructor Detail |
---|
public ObserverManager(Class<?> ownerType, Class<?>... parameterTypes)
The error handling policy used is ObserverManager.NotificationPolicy.StopOnError
,
i.e. the notification will stop in case the notification of
an observer fails.
ownerType
- The owner type of this manager;
cannot be null.parameterTypes
- The formal parameter types required by all
annotated methods used to notify observers
stored in this manager, ignoring primitive
types; can be null.
NullPointerException
- If ownerType
is null.public ObserverManager(ErrorHandler errorHandler, Class<?> ownerType, Class<?>... parameterTypes)
errorHandler
- The error handler determining if the notification
should continue in case of errors; cannot be null.ownerType
- The owner type of this manager;
cannot be null.parameterTypes
- The formal parameter types required by all
annotated methods used to notify observers
stored in this manager, ignoring primitive
types; can be null.
NullPointerException
- If errorHandler
or ownerType
are null.public ObserverManager(ObserverManager manager)
manager
- The manager to copy; cannot be null.
NullPointerException
- If manager
is null.Method Detail |
---|
public <T> boolean addObserver(Class<? extends T> clazz, @Participant(value="ConcreteObserver") T observer)
observer
to this
manager, associated with the methods annotated in the class
supplied as clazz
with a context type
the owner type
of this manager is
assignable to, if any.
observer
is used as the target for all non-static
methods registered by this invocation.
Adding observer
multiple times has no effect.
T
- The type of clazz
.clazz
- The class literal supplying the type to fetch the
methods from; cannot be null.observer
- The observer; cannot be null.
observer
was added as an observer,
false if not.
NullPointerException
- If either argument is null.removeObserver(Class, Object)
public boolean addObserver(@Participant(value="ConcreteObserver") Object observer)
observer
to this
manager, associated with the methods annotated in the class
of object
with a context type
the owner type
of this manager is
assignable to, if any.
observer
is used as the target for all non-static
methods registered by this invocation.
Adding observer
multiple times has no effect.
addObserver
in interface Observable<Object>
observer
- The observer; cannot be null.
observer
was added as an observer,
false if not.
NullPointerException
- If observer
is null.removeObserver(Object)
public Map<Method,List<Object>> getObserverMethods()
Modifying the returned map will not affect this manager.
public Collection<Object> getObservers()
Observable
No specific order is maintained.
Modifying the returned collection will not affect this observable.
getObservers
in interface Observable<Object>
public Class<?> getOwnerType()
All methods associated with a registered observer
in this manager is annotated with a context
type
this type is assignable to.
public boolean notifyObservers(Object... arguments)
arguments
. In case the notification to a given observer (per method) fails, the error handler supplied at construction time will try and handle the error. If the error is manageable, the notification will continue; otherwise an exception is thrown.
No specific order of notification among observers is enforced.
arguments
- The arguments to supply to each observer.
IllegalArgumentException
- If arguments
does not
match the formal observer parameter types specified at
construction time.
RuntimeException
- If the notification failed in a manner
that could not be handled by this manager.private boolean remove(Method method, Object observer)
method
from the observer supplied as observer
.
If method
is the last method associated with observer
,
observer
will also be removed.
method
- The specific method to remove; cannot be null.observer
- The observer; cannot be null.
method
was removed, false if not.
NullPointerException
- If either argument is null.public <T> boolean removeObserver(Class<? extends T> clazz, T observer)
observer
from this
manager.
If object
is not associated with this manager, this
method does nothing.
T
- The type of clazz
.clazz
- The class literal supplying the type; cannot be null.observer
- The observer to remove; cannot be null.
observer
was removed, false if not.
NullPointerException
- If either argument is null.addObserver(Class, Object)
public boolean removeObserver(Object observer)
observer
from this
manager.
If object
is not associated with this manager, this
method does nothing.
removeObserver
in interface Observable<Object>
observer
- The observer to remove; cannot be null.
observer
was removed, false if not.
NullPointerException
- If observer
is null.addObserver(Object)
public int size()
public String toString()
toString
in class Object
|
Gunni Rode / rode.dk | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |