Package org.openscience.cdk
Class DynamicFactory
java.lang.Object
org.openscience.cdk.DynamicFactory
A factory class for constructing
ICDKObject
and IChemObject
implementations. Instances can be created by registering a construction key
(DynamicFactory.ConstructorKey
) with a corresponding creator (DynamicFactory.Creator
). In
most cases a class can simply be registered by providing an interface and an
implementation register(Class, Class)
.
Internally the factory stores the object creators in a symbol table which
allows near constant time access for all registered classes.
In cases of a non-direct parameter match (e.g. Atom(Atom)
can resolve
to Atom(Element)
) the constructor is matched by invoking find(ConstructorKey)
. If a constructor was found the new key will be
registered with cache to avoid the overhead of finding the correct
constructor again.
// create an instance of the factory
DynamicFactory factory = new DynamicFactory(5);
// register some implementations
factory.register(IAtom.class, Atom.class);
factory.register(IElement.class, Element.class);
factory.register(IAtomContainer.class, AtomContainer.class);
// create an instance using the default constructor
IAtom a1 = factory.ofClass(IAtom.class);
// create an instance using a parametrised constructor
IAtom c = factory.ofClass(IAtom.class, "C");
// using a custom creator to actually invoke a constructor
// import static org.openscience.cdk.DynamicFactory.key;
// import static org.openscience.cdk.DynamicFactory.BasicCreator;
factory.register(key(IBond.class, IAtom[].class),
new BasicCreator<IAtom>(null) {
public IAtom create(Object[] objects) {
return new Bond((IAtom[]) objects);
}
});
It is not always convenient to specify a custom DynamicFactory.Creator
for
every construction type but the objects may still need some modification
directly after creation. The factory provides DynamicFactory.CreationModifier
which
is invoked directly after object creation. This allows changing the default
of creation. As an example it is possible to set a non-null charge on all
atoms that are created.
// import static org.openscience.cdk.DynamicFactory.CreationModifier;
factory.register(IAtom.class, Atom.class,
new CreationModifier<Atom>() {
public void modify(Atom atom) {
atom.setFormalCharge(0);
}
}));
It is also possible change the object creation based on the input parameters.
factory.register(key(IAtom.class, String.class),
new DynamicFactory.BasicCreator<IAtom>() {
public IAtom create(Object[] objects) {
String symbol = (String) objects[0];
return "R".equals(symbol)
? new PseudoAtom(symbol)
: new Atom(symbol);
}
});
factory.ofClass(IAtom.class, "C"); // IAtom
factory.ofClass(IAtom.class, "R"); // IPseudoAtom
- Author:
- John May
- Source code:
- main
- Belongs to CDK module:
- core
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic class
A simple creator that helps in creating an anonymous classes for a creator.static class
A class which encapsulates the information about an interface (of this implementation) and the parameter types of the constructor.static interface
An interface that allows posterior modification of an instance after it has been created.static interface
An interface that wraps object creation via theDynamicFactory.Creator.create(Object[])
method.protected static class
A default interface provider implementation that simply returns the classes fromClass.getInterfaces()
.static interface
An interface that can provide which interfaces the given class implements. -
Constructor Summary
ConstructorsConstructorDescriptionDynamicFactory
(int n) Create a new default factory with an expected number of registered classes and a default interface provider.DynamicFactory
(DynamicFactory.InterfaceProvider interfaceProvider, int n) Create a new default factory with an expected number of registered classes and an interface provider. -
Method Summary
Modifier and TypeMethodDescription<T extends ICDKObject>
Set<Class<?>>implementorsOf
(Class<T> intf) Access the registered implementations for a given interface.Creates a constructor key for use in accessing constructors.<T extends ICDKObject>
TConstruct an implementation using the default constructor.<T extends ICDKObject>
TConstruct an implementation using a constructor whose parameters match that of the provided objects.<T extends ICDKObject>
booleanRegisters a class with the factory.<S extends ICDKObject,
T extends S>
booleanregister
(Class<S> intf, Class<T> impl, DynamicFactory.CreationModifier<T> modifier) Explicitly register a concrete class with a provided interface and a given modifier.<S extends ICDKObject,
T extends S>
booleanregister
(Class<S> intf, Constructor<T> constructor) Register a specific constructor with an explicit interface.<S extends ICDKObject,
T extends S>
booleanregister
(Class<S> intf, Constructor<T> constructor, DynamicFactory.CreationModifier<T> modifier) Register a specific constructor with a creation modifier to an explicit interface.<T extends ICDKObject>
booleanExplicitly register a concrete class with a provided interface.<T> DynamicFactory.Creator<T>
register
(DynamicFactory.ConstructorKey key, DynamicFactory.Creator<T> creator) Register a constructor key with a definedDynamicFactory.Creator
.Provides a list of all possible constructor keys for the provided interface.
-
Constructor Details
-
DynamicFactory
Create a new default factory with an expected number of registered classes and an interface provider. The interface provider is used when registering an implementation without a specified interfaceregister(Class)
.- Parameters:
interfaceProvider
- provides the interfaces of a given implementation classn
- the expected number of constructors that will be stored.- See Also:
-
DynamicFactory
public DynamicFactory(int n) Create a new default factory with an expected number of registered classes and a default interface provider. The default interface provider simply invokesClass.getInterfaces()
when registering an implementation without an explicit interfaceregister(Class)
.- Parameters:
n
- the expected number of constructors that will be stored.
-
-
Method Details
-
register
Registers a class with the factory. The interfaces of the class will be checked to see if they are CDK interfaces before they are registered. This method is provided for utility but will register the implementation with all valid interfaces. If a restricted registration is required then the saferregister(Class, Class)
can be used.- Parameters:
impl
- a concrete class- Throws:
IllegalArgumentException
- thrown if a non-concrete class is registered- See Also:
-
register
Explicitly register a concrete class with a provided interface. TheDynamicFactory.Creator
will be automatically created for all public constructors.- Parameters:
intf
- the interface class to registerimpl
- the concrete class which should implement the interface class- Returns:
- whether registration was successful
-
register
public <S extends ICDKObject,T extends S> boolean register(Class<S> intf, Class<T> impl, DynamicFactory.CreationModifier<T> modifier) Explicitly register a concrete class with a provided interface and a given modifier. TheDynamicFactory.Creator
will be automatically created for all public constructors. The modifier is incorporated into theDynamicFactory.Creator
and is invoked directly after instantiation.// import static org.openscience.cdk.DynamicFactory.CreationModifier; factory.register(IAtom.class, Atom.class, new CreationModifier<Atom>() { public void modify(Atom atom) { atom.setFormalCharge(0); } }));
- Type Parameters:
S
- interface typeT
- implementation type (must extend interface)- Parameters:
intf
- the interface class to registerimpl
- the concrete class which should implement the interface classmodifier
- modify a instance after creation- Returns:
- whether registration was successful
-
register
public <S extends ICDKObject,T extends S> boolean register(Class<S> intf, Constructor<T> constructor) Register a specific constructor with an explicit interface.// only register construction of IAtom using a string - Atom("C") factory.register(IAtom.class, Atom.class.getConstructor(String.class));
- Type Parameters:
S
- interface typeT
- implementation type (must extend interface)- Parameters:
intf
- the interfaceconstructor
- a constructor which builds the given interface- Returns:
- whether the constructor was registered
-
register
public <S extends ICDKObject,T extends S> boolean register(Class<S> intf, Constructor<T> constructor, DynamicFactory.CreationModifier<T> modifier) Register a specific constructor with a creation modifier to an explicit interface.// only register construction of IAtom using a string - Atom("C") factory.register(IAtom.class, Atom.class.getConstructor(String.class), new DynamicFactory.CreationModifier<Atom>() { public void modify(Atom instance) { instance.setFormalCharge(0); } });
- Type Parameters:
S
- interface typeT
- implementation type (must extend interface)- Parameters:
intf
- the interfaceconstructor
- a constructor which builds the given interface- Returns:
- whether the constructor was registered
-
register
public <T> DynamicFactory.Creator<T> register(DynamicFactory.ConstructorKey key, DynamicFactory.Creator<T> creator) Register a constructor key with a definedDynamicFactory.Creator
. The key defines the interface and parameters of the creation and the creator actually creates the object.// import static org.openscience.cdk.DynamicFactory.key; factory.register(key(IBond.class, IAtom[].class), new BasicCreator<IAtom>(null) { public IAtom create(Object[] objects) { return new Bond((IAtom[]) objects); } });
- Type Parameters:
T
- type of object that will be created- Parameters:
key
- construction key, defines interface and parameter typescreator
- creates the actual object- Returns:
- the registered creator - null if not registered
-
key
Creates a constructor key for use in accessing constructors. The key combines the interface and types in a single instance which we can then use in a map.- Parameters:
intf
- the interface to build the key fortypes
- the classes that the the constructor requires- Returns:
- a constructor key which can be used to lookup a constructor
-
ofClass
Construct an implementation using a constructor whose parameters match that of the provided objects.- Type Parameters:
T
- the type of the class- Parameters:
intf
- the interface to construct an instance of- Returns:
- an implementation of provided interface
- Throws:
IllegalArgumentException
- thrown if the implementation can not be constructedIllegalArgumentException
- thrown if the provided class is not an interface
-
ofClass
Construct an implementation using the default constructor. This provides some speed boost over invokingofClass(Class, Object...)
.- Type Parameters:
T
- the type of the class- Parameters:
intf
- the interface to construct an instance of- Returns:
- an implementation of provided interface constructed using the default constructor.
- Throws:
IllegalArgumentException
- thrown if the implementation can not be constructedIllegalArgumentException
- thrown if the provided class is not an interface
-
implementorsOf
Access the registered implementations for a given interface.- Type Parameters:
T
- the type of the interface- Parameters:
intf
- an interface which has registered implementations in the factory- Returns:
- set of implementation classes (empty if none found)
-
suggest
Provides a list of all possible constructor keys for the provided interface.- Parameters:
intf
- an interface to find all constructors for- Returns:
- an iterator of constructor keys
-