Я злоупотребляю / неправильно использую отражение Java? - PullRequest
6 голосов
/ 04 августа 2011

Я пишу программу для чтения данных из файла, который может быть в одном из нескольких форматов (на самом деле, в разных версиях одного и того же формата), и я использую отражение для вызова соответствующей функции для каждого формата. Предполагая, что формат файла представляет собой число, указанное в первом байте файла:

Class DataFile extends Model {
...
Blob file
...
public void parse() throws Exception{

    InputStream is = file.get();

    Class c = Class.forName("models.DataFile");
    Method m = c.getMethod("parse_v"+is.read(), (Class []) null);
    m.invoke(this, (Object []) null);
}

public void parse_v0() throws Exception{
   ...
}

public void parse_v1() throws Exception{
   ...
}
}

У меня вопрос, злоупотребляю ли я / неправильно использую отражение? У меня такое ощущение, что я должен использовать наследование и создавать разные классы для каждого типа файлов с собственной процедурой "синтаксического анализа", но я не знаю тип файла, пока не начну синтаксический анализ ... и тогда я не смогу "уменьшить" и просто используйте что-то вроде ((DataFile_v1) this).parse(), поэтому я немного растерялся.

Спасибо за ваше время!

Ответы [ 5 ]

7 голосов
/ 04 августа 2011

В этом нет ничего принципиального, но более гибкий и расширяемый способ сделать то же самое - использовать информацию о версии в качестве ключа в Map и иметь значения в объектах-обработчиках Map be , Тогда любой код может зарегистрировать обработчик (все обработчики могут реализовать общий интерфейс), и ваш код читателя может просто найти обработчик в Map и вызвать его.

Обязательно разберитесь со случаем, когда Map не содержит обработчик для конкретной версии!

2 голосов
/ 04 августа 2011

Если вы сделаете интерфейс DataFile, определите метод parse и реализуете интерфейс с несколькими классами (DataFile_v1 и т. Д.), Тогда вызывающему коду не нужно знать, какая реализация была выбрана.

DataFile dataFile = dataFileFactory.getForVersion(is.read());
dataFile.parse(file);

Я бы сказал, что это лучший подход с точки зрения общего дизайна. Однако в какой-то момент вам нужно будет создать какое-то отображение между номером версии и реализациями DataFile. (В этом случае я делаю это в воображаемом dataFileFactory.) Вам нужно будет определить, будет ли более уместным выбрать реализацию, используя отражение или какой-либо другой метод.

0 голосов
/ 04 августа 2011

Вы можете использовать коллекцию, но использование отражений также ищет коллекцию.Если ваше отображение не меняется, я бы использовал отражения.

getClass().getMethod("parse_v"+is.read()).invoke(this);
0 голосов
/ 04 августа 2011

То, что вы делаете, не плохо. Если вы хотите иметь разные парсеры в разных классах, вы не можете, как вы говорите, преуменьшать значение, но вы можете создать экземпляр нового объекта парсера. Таким образом, ваш существующий класс будет фасадом перед фактическими синтаксическими анализаторами, которые не создаются, пока вы не узнаете, какой формат вы анализируете.

0 голосов
/ 04 августа 2011

Я думаю, что здесь можно использовать отражение. Альтернативой может быть использование наследования или перечисления (т. Е. шаблон стратегии ), а также отображение кода версии на соответствующую стратегию. После того, как вы инициализировали все нужные отображения, вы просто получаете правильный объект парсера с карты и вызываете его. Однако для настройки этого решения все еще требуется значительное количество стандартного кода, что снижает его читабельность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...