Class DynamicFactory


  • public class DynamicFactory
    extends Object
    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
    • Constructor Detail

      • DynamicFactory

        public DynamicFactory​(DynamicFactory.InterfaceProvider interfaceProvider,
                              int n)
        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 interface register(Class).
        Parameters:
        interfaceProvider - provides the interfaces of a given implementation class
        n - the expected number of constructors that will be stored.
        See Also:
        DynamicFactory(int)
      • 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 invokes Class.getInterfaces() when registering an implementation without an explicit interface register(Class).
        Parameters:
        n - the expected number of constructors that will be stored.
    • Method Detail

      • register

        public <T extends ICDKObject> boolean register​(Class<T> intf,
                                                       Class<? extends T> impl)
        Explicitly register a concrete class with a provided interface. The DynamicFactory.Creator will be automatically created for all public constructors.
        Parameters:
        intf - the interface class to register
        impl - 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. The DynamicFactory.Creator will be automatically created for all public constructors. The modifier is incorporated into the DynamicFactory.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 type
        T - implementation type (must extend interface)
        Parameters:
        intf - the interface class to register
        impl - the concrete class which should implement the interface class
        modifier - 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 type
        T - implementation type (must extend interface)
        Parameters:
        intf - the interface
        constructor - 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 type
        T - implementation type (must extend interface)
        Parameters:
        intf - the interface
        constructor - 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 defined DynamicFactory.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 types
        creator - creates the actual object
        Returns:
        the registered creator - null if not registered
      • key

        public static DynamicFactory.ConstructorKey key​(Class<?> intf,
                                                        Class<?>... types)
        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 for
        types - the classes that the the constructor requires
        Returns:
        a constructor key which can be used to lookup a constructor
      • ofClass

        public <T extends ICDKObject> T ofClass​(Class<T> intf,
                                                Object... objects)
        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 constructed
        IllegalArgumentException - thrown if the provided class is not an interface
      • ofClass

        public <T extends ICDKObject> T ofClass​(Class<T> intf)
        Construct an implementation using the default constructor. This provides some speed boost over invoking ofClass(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 constructed
        IllegalArgumentException - thrown if the provided class is not an interface
      • implementorsOf

        public <T extends ICDKObjectSet<Class<?>> implementorsOf​(Class<T> intf)
        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

        public Iterator<DynamicFactory.ConstructorKey> suggest​(Class<?> intf)
        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