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

dk.rode.thesis.proxy
Class SequenceProxyFactory

java.lang.Object
  extended by dk.rode.thesis.proxy.SequenceProxyFactory

public class SequenceProxyFactory
extends Object

A sequence proxy factory creates various dynamic proxies for any type of sequence.

The proxies are all instances of the java.lang.reflect.Proxy class. Each created proxy can be cast into any interface implemented by the proxied sequence.

Six different kinds of dynamic sequence proxies can be created by this factory:

  1. getLoggableSequence(Sequence): returns a sequence proxy that will record and time all access to the proxied sequence if and only if all access is through the proxy only.

  2. getSynchronisedSequence(Sequence): returns a sequence proxy that guarantees thread-safe access to the proxied sequence if and only if all access is through the proxy only. The lock used synchronise on is the proxied sequence.

  3. getNonResettableSequence(Sequence): returns a sequence proxy that disallows the proxied sequence to be reset if and only if all access is through the proxy only.

  4. getImmutableSequence(Sequence): returns a sequence proxy that disallows the proxied sequence to be reset, advanced, or copied if and only if all access is through the proxy only. Copying will simply return the proxy instance, not the proxied object.

  5. getVirtualSequence(InstantiableTypeLiteral, Object...): returns a virtual sequence proxy that will create the actual sequence to use once the first method declared in the specific Sequence type or a super-interface is invoked.

  6. getSharedSequence(Sequence): returns a smart pointer proxy that will allow a given sequence to be shared among copies of it until a given copy invokes either Sequence.next() or Sequence.reset(), which will detach the copy from the reference and copy the sequence used internally.

Factory methods 2-4 create dynamic proxies that mimics the behaviour of the fixed sequence proxy classes SynchronisedSequence, NonResettableSequence, and ImmutableSequence, respectively, but the returned dynamic proxies can still be cast into any interface implemented by the proxied sequence.

It is perfectly legal to create sequence proxies based on other sequence proxies.

Implementation notes:
The factory defers the actual proxy creation to the ProxyFactory class, which allows creation of proxies based on any type. The ProxyFactory could have been inherited, but composition is chosen instead to keep the interface of this class clean and focused on sequences.

Each method used to create a sequence proxy defined in this class is an application of the Factory Method pattern.

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

Field Summary
private  Method copy
          The copy() method defined in the Sequence interface.
(package private) static ProxyFactory factory
          The singleton proxy factory used to create the proxy objects representing sequences.
private  Method next
          The next() method defined in the Sequence interface.
private  Method reset
          The reset() method defined in the Sequence interface.
 
Constructor Summary
SequenceProxyFactory()
          No-arg constructor.
 
Method Summary
<E> Sequence<E>
getImmutableSequence(Sequence<E> sequence)
          Returns a sequence proxy implementing all interfaces sequence implements that will disallow Sequence.reset(), Sequence.next(), and Sequence.copy() to alter sequence if and only if all access is though the returned proxy.
<E> Sequence<E>
getLoggableSequence(Sequence<E> sequence)
          Returns a sequence proxy implementing all interfaces sequence implements that will log all access to sequence if and only if all access is though the returned proxy.
<E> Sequence<E>
getNonResettableSequence(Sequence<E> sequence)
          Returns a sequence proxy implementing all interfaces sequence implements that will disallow Sequence.reset() to be invoked for sequence if and only if all access is though the returned proxy.
<E> Sequence<E>
getSharedSequence(Sequence<E> sequence)
          Creates a smart pointer based on the sequence supplied as sequence.
<E> Sequence<E>
getSynchronisedSequence(Sequence<E> sequence)
          Returns a sequence proxy implementing all interfaces sequence implements that will ensure synchronised access to sequence if and only if all access is though the returned proxy.
<E,T extends Sequence<E>>
T
getVirtualSequence(InstantiableTypeLiteral<T> type, Object... arguments)
          Creates a virtual sequence based on the sequence type T.
 boolean isProxied(Sequence<?> sequence)
          Returns true if sequence has at least one created proxy sequence associated with it, false if not.
 boolean isProxy(Sequence<?> sequence)
          Returns true if sequence is a proxy sequence created by a sequence proxy factory, false if not.
 String toString()
          Returns the string representation of this factory.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

copy

private final Method copy
The copy() method defined in the Sequence interface.

Never null.


factory

static final ProxyFactory factory
The singleton proxy factory used to create the proxy objects representing sequences.

Never null.


next

private final Method next
The next() method defined in the Sequence interface.

Never null.


reset

private final Method reset
The reset() method defined in the Sequence interface.

Never null.

Constructor Detail

SequenceProxyFactory

public SequenceProxyFactory()
No-arg constructor.

Method Detail

getImmutableSequence

@ParticipantUsage(value="Proxy",
                  type=Sequence.class)
public <E> Sequence<E> getImmutableSequence(@Participant(value="RealSubject")
                                                                                    Sequence<E> sequence)
Returns a sequence proxy implementing all interfaces sequence implements that will disallow Sequence.reset(), Sequence.next(), and Sequence.copy() to alter sequence if and only if all access is though the returned proxy.

The copy() method simply returns the proxy instance, not the proxied object.

The returned proxy has similar functionality to the ImmutableSequence class, but the returned proxy can still be cast into any interface implemented by sequence, though not the actual sequence type (class) itself. Trying to cast the returned proxy into the actual type (class) of sequence will cause a class cast exception to be thrown!

Type Parameters:
E - The type of values delivered by sequence.
Parameters:
sequence - The sequence to proxy; cannot be null.
Returns:
The proxy sequence; never null.
See Also:
ImmutableSequence

getLoggableSequence

@ParticipantUsage(value="Proxy",
                  type=Sequence.class)
public <E> Sequence<E> getLoggableSequence(@Participant(value="RealSubject")
                                                                                   Sequence<E> sequence)
Returns a sequence proxy implementing all interfaces sequence implements that will log all access to sequence if and only if all access is though the returned proxy.

The returned proxy can be cast into any interface implemented by sequence, but not the actual sequence type (class) itself. Trying to cast the returned proxy into the actual type (class) of sequence will cause a class cast exception to be thrown!

Type Parameters:
E - The type of values delivered by sequence.
Parameters:
sequence - The sequence to proxy; cannot be null.
Returns:
The proxy sequence; never null.

getNonResettableSequence

@ParticipantUsage(value="Proxy",
                  type=Sequence.class)
public <E> Sequence<E> getNonResettableSequence(@Participant(value="RealSubject")
                                                                                        Sequence<E> sequence)
Returns a sequence proxy implementing all interfaces sequence implements that will disallow Sequence.reset() to be invoked for sequence if and only if all access is though the returned proxy.

The returned proxy has similar functionality to the NonResettableSequence class, but the returned proxy can still be cast into any interface implemented by sequence, though not the actual sequence type (class) itself. Trying to cast the returned proxy into the actual type (class) of sequence will cause a class cast exception to be thrown!

Type Parameters:
E - The type of values delivered by sequence.
Parameters:
sequence - The sequence to proxy; cannot be null.
Returns:
The proxy sequence; never null.
See Also:
NonResettableSequence

getSharedSequence

public <E> Sequence<E> getSharedSequence(@Participant(value="RealSubject")
                                         Sequence<E> sequence)
Creates a smart pointer based on the sequence supplied as sequence.

Call the returned proxy X, using sequence as its internal sequence, which may be shared. Hence, sequence will be shared among all copies of X (inclusive), say X and Y, until a given copy, say Y, invokes either next() or reset(). This will copy sequence and detach Y. Y will henceforth use the copy of sequence just made, and Y can be shared (copied) as well, say into Z, which will use the same internal sequence as Y, and so forth.

The returned proxy will not be registered to this factory.

Type Parameters:
E - The type of sequence values delivered by sequence.
Parameters:
sequence - The sequence to share; cannot be null.
Returns:
A proxy representing the shared sequence; never null.
Throws:
NullPointerException - If sequence is null.

getSynchronisedSequence

@ParticipantUsage(value="Proxy",
                  type=Sequence.class)
public <E> Sequence<E> getSynchronisedSequence(@Participant(value="RealSubject")
                                                                                       Sequence<E> sequence)
Returns a sequence proxy implementing all interfaces sequence implements that will ensure synchronised access to sequence if and only if all access is though the returned proxy.

The returned proxy has similar functionality to the SynchronisedSequence class, but the returned proxy can still be cast into any interface implemented by sequence, though not the actual sequence type (class) itself. Trying to cast the returned proxy into the actual type (class) of sequence will cause a class cast exception to be thrown!

Type Parameters:
E - The type of values delivered by sequence.
Parameters:
sequence - The sequence to proxy; cannot be null.
Returns:
The proxy sequence; never null.
See Also:
SynchronisedSequence

getVirtualSequence

@ParticipantUsage(value="Proxy",
                  type=Sequence.class)
public <E,T extends Sequence<E>> T getVirtualSequence(@Participant(value="RealSubject")
                                                                                              InstantiableTypeLiteral<T> type,
                                                                                              Object... arguments)
Creates a virtual sequence based on the sequence type T.

Once the first method declared in T, or in a super-type of T, is invoked on the returned proxy, the proxy creates the actual proxied sequence that will be used as the subject hence forth.

The returned proxy is not registered to this factory as the proxied object is not yet created. Hence, any call to isProxy(Sequence) with the returned proxy as the argument will return false!

The returned proxy can be cast into any super-interface of T, or T itself if T is not a class.

Type Parameters:
E - The type of sequence values delivered by the sequence.
T - The actual type of sequence to create a virtual proxy for.
Parameters:
type - The type literal representing the actual type; cannot be null.
arguments - The arguments used to construct the proxied sequence.
Returns:
The virtual proxy representing the sequence to create; never null.
Throws:
NullPointerException - If type is null.

isProxied

public boolean isProxied(Sequence<?> sequence)
Returns true if sequence has at least one created proxy sequence associated with it, false if not.

sequence may be a proxy itself.

Parameters:
sequence - The sequence to test; cannot be null.
Returns:
True if sequence has at least one associated proxy, false if not.
Throws:
NullPointerException - If sequence is null.
See Also:
isProxy(Sequence)

isProxy

public boolean isProxy(Sequence<?> sequence)
Returns true if sequence is a proxy sequence created by a sequence proxy factory, false if not.

Parameters:
sequence - The sequence to test; cannot be null.
Returns:
True if sequence is a proxy sequence, false if not.
Throws:
NullPointerException - If sequence is null.
See Also:
isProxied(Sequence)

toString

public String toString()
Returns the string representation of this factory.

Overrides:
toString in class Object
Returns:
The string representation; never null.

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.