Заводы в Java без оператора switch
Я пытаюсь построить объект фабрики, но не могу найти хороший способ сделать это в Java.
Приложение, которое я пишу, используется для обработки файлов в различных форматах, поэтому существует CodecInterface, который применяется ко всем классам, которые используются для чтения и записи файлов. Давайте предположим, что это определяет следующие методы. Каждый из этих файлов имеет уникальную назначенную человеком строку идентификатора, которая используется для идентификации кодировщика \ декодера.
String read();
void write(String data);
String getID();
Класс фабрики будет иметь метод create, который предназначен для создания экземпляров этих классов кодеков. Я полагаю, что подпись метода будет выглядеть примерно так.
static CodecInterface CodecFactory.create(String filename, String codecid, String args);
Имя файла - это имя файла для чтения / записи, а кодекид - это уникальный идентификатор, указывающий, какой кодек использовать. Параметр args представляет собой строку аргументов, передаваемых генерируемому объекту декодера / кодера. Возвращаемое значение должно быть экземпляром запрошенного объекта кодека.
Все примеры Factory, которые я видел, обычно содержат инструкцию switch внутри метода create, который создает экземпляр объекта в зависимости от идентификатора. Я хочу избежать этого, так как это не кажется правильным, и это также означает, что список более или менее фиксирован, если вы не измените метод create. В идеале я хотел бы использовать что-то вроде словаря (индексируемого идентификатором кодека), который содержит что-то, что можно использовать для создания экземпляра классов кодека, которые я хочу (я назову этот загадочный класс ClassReference). Снова, чтобы использовать некоторый квази-Java-код, вот то, что я думал как тело для метода создания.
static Dictionary<String, ClassReference>;
static CodecInterface CodecFactory.create(String filename, String codecid, String args);
{
ClassReference classreference;
classreference = codeclibrary(codecid);
return classreference.instanceOf(args);
}
Словарь идентификаторов достаточно прост, но я не могу понять, каким должен быть ClassReference. Ссылка на класс должна позволить мне создать экземпляр нужного класса, как в примере выше.
Посмотрев вокруг в Интернете, метод класса и instanceOf, похоже, движутся в правильном направлении, но я не нашел ничего, что бы соединило их вместе. Как дополнительная сложность, конструкторы для создаваемых объектов будут иметь аргументы.
Любые советы о том, что я должен смотреть на, будет принята с благодарностью.
Заранее спасибо.
РЕШЕНИЕ
Спасибо всем за ваш совет. В итоге я взял кусочки из всех ваших предложений и придумал следующее, которое, кажется, работает так, как я хотел.
Обратите внимание, что я пропустил большую часть кода проверки работоспособности \ ошибок, чтобы показать важные биты.
import java.lang.reflect.Constructor;
import java.util.HashMap;
public class CodecFactory
{
private static HashMap<String, Class<? extends CodecInterface>> codecs;
static
{
codecs = new HashMap<String, Class<? extends CodecInterface>>();
//Register built-in codecs here
register("codecA", CodecA.class);
register("codecB", CodecB.class);
register("codecC", CodecC.class);
}
public static void register(String id, Class<? extends CodecInterface> codec)
{
Class<? extends CodecInterface> 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<? extends CodecInterface> 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;
}
}