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

dk.rode.thesis.factorymethod
Class TypedFactory<T,P>

java.lang.Object
  extended by dk.rode.thesis.meta.reflect.TypeLiteral<T>
      extended by dk.rode.thesis.meta.reflect.InstantiableTypeLiteral<T>
          extended by dk.rode.thesis.factorymethod.Factory<T>
              extended by dk.rode.thesis.factorymethod.TypedFactory<T,P>
Type Parameters:
T - The product type created by this factory.
P - The single type of parameters used for the constructor.

@Participant(value="Creator")
public abstract class TypedFactory<T,P>
extends Factory<T>

A generic factory that will create products of type T while only accepting constructor arguments of type P (for all arguments).

Usage: to create instances of Foo<String> using the constructor accepting two String arguments:

   // Create factory...
   TypedFactory<Foo<String>,String> factory1 = 
     new TypedFactory(String.class, 2){}; // anonymous class
     
   // Create products...  
   Foo<String> foo    = factory1.createInstance("Bar", "BarBar");
   Foo<String> foobar = factory1.createInstance("FooBar", "GooBar");
 
To create instances of Goo<String> using the constructor accepting a the generic FooBar<V> type, e.g. FooBar<Integer>:
   
   // Argument(s) type and values...
   TypeLiteral<FooBar<Integer>> type = new TypeLiteral<FooBar<Integer>>(){}; // anonymous class
  
   FooBar<Integer> fb1 = new FooBar<Integer>(..);
   FooBar<Integer> fb2 = new FooBar<Integer>(..);
   
   // Factory...
   TypedFactory<Goo<String>,FooBar<Integer>> factory2 = 
     new TypedFactory(type){}; // e.g. TypedFactory(type, 1)
   
     
   // Create products...  
   Goo<String> goo1 = factory2.createInstance(fb1); // FooBar<Integer>
   Goo<String> goo2 = factory2.createInstance(fb2); // FooBar<Integer>
   
 
The constructor to create new instances of T is fetched ignoring primitive types, e.g. a formal parameter P of type Integer will match both Integer and int.

Implementation notes:
This factory is classified as a Factory Method, not an Abstract Factory, because its traits most closely resemble those described for Factory Method by Gamma et al. [Gamma95, p.107-116], but it is a judgement call. We see it as a variant of the Creator class [Gamma95, p.113], which uses templates to determine the actual type of product to create. We still use it in the Abstract Factory implementation as well, though. These are the reasons why it is named Factory, and not Creator.

While the creation process can enforce proper type on supplied factory method arguments, the number of arguments supplied may still be illegal. This can be handled by making explicit factory methods, i.e. specific factories, or perhaps by ignoring redundant arguments.

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

Field Summary
 
Fields inherited from class dk.rode.thesis.meta.reflect.TypeLiteral
type
 
Constructor Summary
protected TypedFactory(Class<P> parameterType)
          Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting a single parameter of type parameterType.
protected TypedFactory(Class<P> parameterType, int parameters)
          Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting the number of parameters supplied as parameters of the type parameterType.
protected TypedFactory(TypeLiteral<P> parameterType)
          Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting a single parameter of type parameterType.
protected TypedFactory(TypeLiteral<P> parameterType, int parameters)
          Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting the number of parameters supplied as parameters of the type parameterType.
 
Method Summary
<S extends P>
T
createInstance(S... arguments)
          Returns a new instance of the type represented by this factory using the arguments supplied as arguments.
private static Class<?>[] toClassArray(Class<?> type, int length)
          Creates an array of length length storing the type supplied as type at each index.
private static Class<?>[] toClassArray(TypeLiteral<?> typeLiteral, int length)
          Creates an array of length length storing the raw type of typeLiteral at each index.
 
Methods inherited from class dk.rode.thesis.factorymethod.Factory
toString
 
Methods inherited from class dk.rode.thesis.meta.reflect.InstantiableTypeLiteral
create, create, create, equals, getConstructor, isInstatiable, isInstatiable, newInstance
 
Methods inherited from class dk.rode.thesis.meta.reflect.TypeLiteral
asClass, asClass, asType, create, create, create, getComponentType, getRawType, getRawType, getType, hashCode
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Constructor Detail

TypedFactory

protected TypedFactory(Class<P> parameterType)
                throws NoSuchMethodException
Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting a single parameter of type parameterType.

The constructor is made accessible if not already. New instances of T must be created with the createInstance(Object...) factory method.

Parameters:
parameterType - The formal parameter type for the declared constructor to use; cannot be null.
Throws:
NullPointerException - If parameterType is null.
IllegalArgumentException - If this class is not generic, if T has no raw type, or if the raw raw represents a non instantiable class.
NoSuchMethodException - If no such constructor is declared in the raw type of T.

TypedFactory

protected TypedFactory(Class<P> parameterType,
                       int parameters)
                throws NoSuchMethodException
Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting the number of parameters supplied as parameters of the type parameterType.

The constructor is made accessible if not already. New instances of T must be created with the createInstance(Object...) factory method.

Parameters:
parameterType - The formal parameter types for the declared constructor to use; cannot be null.
parameters - The number of constructor parameters; cannot be negative.
Throws:
NullPointerException - If parameterType is null.
IllegalArgumentException - If this class is not generic, if T has no raw type, if the raw raw represents a non instantiable class, or if parameters is negative.
NoSuchMethodException - If no such constructor is declared in the raw type of T.

TypedFactory

protected TypedFactory(TypeLiteral<P> parameterType)
                throws NoSuchMethodException
Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting a single parameter of type parameterType.

The constructor is made accessible if not already. New instances of T must be created with the createInstance(Object...) factory method.

Parameters:
parameterType - The formal parameter type for the declared constructor to use; cannot be null.
Throws:
NullPointerException - If parameterType is null.
IllegalArgumentException - If this class is not generic, if T has no raw type, if the raw raw represents a non instantiable class, or if P has no raw type.
NoSuchMethodException - If no such constructor is declared in the raw type of T.

TypedFactory

protected TypedFactory(TypeLiteral<P> parameterType,
                       int parameters)
                throws NoSuchMethodException
Constructor, which creates this factory to create instances of the type represented by the type parameter T using the declared constructor accepting the number of parameters supplied as parameters of the type parameterType.

The constructor is made accessible if not already. New instances of T must be created with the createInstance(Object...) factory method.

Parameters:
parameterType - The formal parameter types for the declared constructor to use; cannot be null.
parameters - The number of constructor parameters; cannot be negative.
Throws:
NullPointerException - If parameterType is null.
IllegalArgumentException - If this class is not generic, if T has no raw type, if the raw raw represents a non instantiable class, if P has no raw type, or if parameters is negative.
NoSuchMethodException - If no such constructor is declared in the raw type of T.
Method Detail

createInstance

public <S extends P> T createInstance(S... arguments)
                 throws Exception
Returns a new instance of the type represented by this factory using the arguments supplied as arguments.

Type Parameters:
S - The actual type of the arguments.
Parameters:
arguments - The arguments to supply to the constructor.
Returns:
A new instance of the type represented by this factory; never null.
Throws:
Exception - If the construction fails.
See Also:
InstantiableTypeLiteral.newInstance(Object...)

toClassArray

private static Class<?>[] toClassArray(Class<?> type,
                                       int length)
Creates an array of length length storing the type supplied as type at each index.

Parameters:
type - The type; cannot be null.
Returns:
An array of length length containing type; never null.
Throws:
NullPointerException - If type is null, or if length is negative.

toClassArray

private static Class<?>[] toClassArray(TypeLiteral<?> typeLiteral,
                                       int length)
Creates an array of length length storing the raw type of typeLiteral at each index.

Parameters:
typeLiteral - The type literal representing the raw type; cannot be null.
Returns:
An array of length length containing the corresponding raw type; never null.
Throws:
NullPointerException - If typeLiteral is null.
IllegalArgumentException - If typeLiteral do not represent a raw type, or if length is negative.

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.