title: Factories in Java without a switch statement
body: <p>I am trying to build a factory object, but having trouble working out a good way of doing it in Java.</p>
  
  <p>The application I am writing is used for processing files in various formats, so there is a CodecInterface which applies to all classes which are used for reading and writing files. Let's assume it defines the following methods. Each of these files has a unique human-designated ID string which is used for id'ing the encoder\decoder.</p>
  
  <pre><code>String read();
  void write(String data);
  String getID();
  </code></pre>
  
  <p>The factory class would have a create method which is intended to create instances of these codec classes. I imagine the method signature would look something like this.</p>
  
  <pre><code>static CodecInterface CodecFactory.create(String filename, String codecid, String args);
  </code></pre>
  
  <p>The filename is the name of the file to read/write, and the codecid is the unique ID indicating what codec to use. The args parameter is a string of arguments passed to the decoder/encoder object being generated. The return of this should be an instance of the requested codec object.</p>
  
  <p>All of the Factory examples I have seen typically have a switch statement inside of the create method which creates an object instance dependent on the ID. I want to avoid doing it this way as it doesn't seem like the 'right' way, and it also means that the list is more or less fixed unless you modify the create method. Ideally I would like to use something like a dictionary (indexed by the codec ID) which contains something which can be used to create an instance of the codec classes I want (I will call this mystery class ClassReference). Again to use some quasi-java code, here is what I was thinking as the body for the create method.</p>
  
  <pre><code>static Dictionary&lt;String, ClassReference&gt;;
  
  static CodecInterface CodecFactory.create(String filename, String codecid, String args);
  {
      ClassReference classreference;
  
      classreference = codeclibrary(codecid);
  
      return classreference.instanceOf(args);
  }
  </code></pre>
  
  <p>The dictionary of ID's is easy enough, but I can't work out what ClassReference should be. Class Reference should allow me to create an instance of the desired class, as in the example above.</p>
  
  <p>From looking around online, the class method, and instanceOf seem to be heading in the right direction, but I haven't found anything which puts the two together. As an added complication, the constructors for the objects being created will have arguments.</p>
  
  <p>Any tips on what I should be looking at would be greatly appreciated.</p>
  
  <p>Thanks in advance.</p>
  
  <p><strong>SOLUTION</strong></p>
  
  <p>Thanks everyone for your advice. I've ended up taking bits and pieces from all of your suggestions and came up with the following which seems to work as I wanted.</p>
  
  <p>Note that I have omitted much of the sanity\error checking code to show off the important bits.</p>
  
  <pre><code>import java.lang.reflect.Constructor;
  import java.util.HashMap;
  
  public class CodecFactory
  {
      private static HashMap&lt;String, Class&lt;? extends CodecInterface&gt;&gt; codecs;
  
      static
      {        
          codecs = new HashMap&lt;String, Class&lt;? extends CodecInterface&gt;&gt;();
  
          //Register built-in codecs here
          register("codecA", CodecA.class);
          register("codecB", CodecB.class);
          register("codecC", CodecC.class);
      }
  
      public static void register(String id, Class&lt;? extends CodecInterface&gt; codec)
      {
          Class&lt;? extends CodecInterface&gt; existing;
  
          existing = codecs.get(id);        
          if(existing == null)
          {
            codecs.put(id, codec);
          }
          else
          {
            //Duplicate ID error handling
          }
      }
  
      public static CodecInterface create(String codecid, String filename, String mode, String arguments)
      {
          Class&lt;? extends CodecInterface&gt; codecclass;
          CodecInterface codec;
          Constructor constructor;
  
          codec = null;
  
          codecclass = codecs.get(codecid);
          if(codecclass != null)
          {
            try
            {
              constructor = codecclass.getDeclaredConstructor(String.class, String.class, String.class, String.class);
              codec = (CodecInterface)(constructor.newInstance(codecid, filename, mode, arguments));
            }
            catch(Exception e)
            {
              //Error handling for constructor/instantiation
            }
          }
  
          return codec;
      }
  }
  </code></pre>