|
Evaluating Software Design Patterns — the "Gang of Four" patterns implemented in Java 6 |
||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Class Summary | |
---|---|
ImmutableSequence<E> | An immutable sequence ensures that invocations of
NonResettableSequence.reset() , ImmutableSequence.next() , and ImmutableSequence.copy() are ignored
for the proxied sequence if and only if
the proxied sequence is accessed through the proxy only. |
Main | Proxy tests. |
NonResettableSequence<E> | A non-resettable sequence ensures that invocations of
NonResettableSequence.reset() are ignored for the proxied sequence
if and only if the proxied sequence is accessed through
the proxy only. |
SequenceProxyFactory | A sequence proxy factory creates various dynamic proxies for
any type of sequence . |
SynchronisedSequence<E> | A synchronised sequence ensures thread-safe access to a
proxied sequence if and only if the proxied
sequence is accessed through the proxy only. |
Enum Summary | |
---|---|
ProxiedPolicy | Additional policies for formatting proxied sequences
into char sequences (not part of the core Proxy implementation). |
Implementations and examples of the Proxy design pattern [Gamma95, p.207].
Intent:
Provide a surrogate placeholder for another object to control access to it.
Sequence
interface, and
the RealSubject participant by any Sequence
implementation, for example
PrimeSequence
,
EnglishAlphabetSequence
,
LongSequence
, etc.
The Proxy participant is represented by the specific
proxy sequence classes defined in this package that control
the access to the real subjects, i.e. sequences, namely
SynchronisedSequence
, and
NonResettableSequence
, and
ImmutableSequence
. They all work via the
Decorator pattern, decorating
the actual Sequence
in order to control access to it.
However, the Proxy participant is also represented by any
sequence proxy returned by the SequenceProxyFactory
class. It utilises Java's java.lang.reflect.Proxy
class that allows for runtime adaptation of interface behaviour using
reflection. The factory defines three specific factory methods
to create proxies based on any Sequence
, mimicking the
SynchronisedSequence
, NonResettableSequence
, and
ImmutableSequence
classes, respectively
SequenceProxyFactory.getSynchronisedSequence(dk.rode.thesis.meta.model.Sequence)
,
SequenceProxyFactory.getNonResettableSequence(dk.rode.thesis.meta.model.Sequence)
,
and SequenceProxyFactory.getImmutableSequence(dk.rode.thesis.meta.model.Sequence)
.
It also supplies a factory method to create a proxy that will log all
access to the proxied object in form of the
SequenceProxyFactory.getLoggableSequence(dk.rode.thesis.meta.model.Sequence)
factory method, as well as the
SequenceProxyFactory.getVirtualSequence(dk.rode.thesis.meta.reflect.InstantiableTypeLiteral, Object...)
factory method that will create a sequence proxy that will delay creation of
the actual Sequence
instance until the first Sequence
method is
invoked. Finally, the SequenceProxyFactory.getSharedSequence(dk.rode.thesis.meta.model.Sequence)
method allows a given sequence to be shared among copies of it until a copy
invokes either next()
or reset()
, which will detach the
copy from the shared reference.
Implementation notes:
The java.lang.reflect.Proxy
class is
quite flexible. It allows casting to any (runtime) implemented interface,
so type information need not be lost for the proxied sequences. A proxy that
works as a (dynamic) Decorator will
effectively change the type (class), so casts and instanceof
tests
will fail for interfaces implemented by the proxied object. This is the case
with the fixed proxy classes created in this package. For example, a
ReversibleSequence
proxied by the
SynchronisedSequence
class will to the context no longer be
reversible, because SynchronisedSequence
do not implement the
ReversibleSequence
interface. A java.lang.reflect.Proxy
instance representing a Sequence
that implements
ReversibleSequence
still allows casts and instanceof
tests.
The price of using java.lang.reflect.Proxy
instances is naturally speed
as the implemented interfaces are accessed using reflection in form of a
java.lang.reflect.InvocationHandler
instance. However, reflection in modern JVM's is quite fast, so it is probably
acceptable in most cases. Also, though a java.lang.reflect.Proxy
object
can be cast into any runtime implemented interface, the original type (class)
information of the proxied object is lost. Class cast exceptions can also occur.
Once a proxy instance is created based on a specific set of interfaces, the
instance represents a unique proxy class that implements these exact interfaces.
Creating another proxy instance with the same ordered set of interfaces will reuse
the proxy class. The returned proxy is thus an instance of that proxy class and
not the original type, for example a LongSequence
.
There are also other problems with such proxies, for example marshaling and
serialization.
For an in-depth introduction to the java.lang.reflect.Proxy
class,
please refer the its JavaDoc documentation.
Gamma et al. define four overall types of proxies: remote proxy,
virtual proxy, protection proxy, and smart reference
[Gamma95, p.208-209]. The getVirtualSequence
method returns a
virtual proxy. The NonResettableSequence
and
ImmutableSequence
classes represent protection proxies
and so do the proxies returned by the getNonResettableSequence
and getImmutableSequence
methods. The SynchornisedSequence
class as well as the proxy returned by the getSynchronisedSequence
method represent a smart reference. The getSharedSequence
method also returns a smart reference, more precisely a
smart pointer. This package defines no remote proxies, but
an example could be a sequence fetching its values using a socket channel
to a sequence on a different machine or JVM delivering the values.
|
Gunni Rode / rode.dk | ||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |