Общий дизайн анализатора файлов в Java с использованием шаблона Strategy


14

Я работаю над продуктом, в котором ответственность одного из модулей состоит в том, чтобы анализировать XML-файлы и выгружать необходимый контент в базу данных. Несмотря на то, что настоящее требование состоит только в разборе файлов XML, я хочу спроектировать свой модуль синтаксического анализа таким образом, чтобы в будущем я мог поддерживать любые типы файлов. Причиной такого подхода является то, что мы создаем этот продукт для конкретного клиента, но планируем продать его другим клиентам в ближайшем будущем. Все системы в экосистеме для текущего клиента производят и потребляют файлы XML, но это может не относиться к другим клиентам.

Что я пробовал до сих пор? (Настоящее время) Я имею в виду следующий дизайн, основанный на шаблоне Стратегии. Я быстро записал код в eclipse, чтобы передать мой дизайн, поэтому было бы замечательно, если другие аспекты, такие как правильный способ обработки исключений, пока игнорируются.

Parser: интерфейс стратегии, который предоставляет метод синтаксического анализа.

 public interface Parser<T> {
        public T parse(String inputFile);
    }

* Причиной использования универсального параметра является разрешение любого возвращаемого типа, а также обеспечение безопасности типов во время компиляции.

ProductDataXmlParser Конкретный класс для анализа файла product.xml, который содержит информацию о продукте. (используя XMLBeans)

public class ProductDataXmlParser implements Parser<ProductDataTYPE> {

    public ProductDataTYPE parse(String inputFile) {
        ProductDataTYPE productDataDoc = null;
            File inputXMLFile = new File(inputFile);

        try {
            productDataDoc = ProductDataDocument.Factory.parse(inputXMLFile);
        } catch(XmlException e) {
            System.out.println("XmlException while parsing file : "+inputXMLFile);
        } catch(IOException e) { 
                 System.out.println("IOException while parsing file : "+inputXMLFile);
        }
        return productDataDoc.getProductData();
    }
} 

где : ProductDataTYPE и ProductDataDocument являются классами XMlBean POJO, созданными с использованием команд xsd и scomp.

Будущее

Если у меня есть файл product.txt для анализа в будущем, я могу определить свой собственный POJO с именем ProductData, который будет содержать необходимое содержимое файла. Затем я могу создать конкретный класс с именем ProductDataFlatFileParser, который реализует интерфейс Parser, и после анализа файла метод parse заполняет для меня ProductData POJO.

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


Должно ли программное обеспечение не сообщать вызывающему абоненту, какие форматы файлов поддерживаются? Как ваше программное обеспечение узнает, какой парсер вызывать?
Томдемайт

Вам нужны отзывы о вашем дизайне , а не о фактической реализации , так что это будет перенесено на программистов, которые обсуждают эту тему.
codeparkle

@tomdemuyt Подумайте, фабричный образец;)
CKing

2
@bot Пользователь SO, который сказал вам разместить это в Code Review, явно ошибался. Вы могли бы прочитать FAQ сайта, прежде чем публиковать его, «кто-то сказал мне это сделать» - не очень хорошая причина для вас что-либо делать. Никто не играет в пинг-понг с этим, кто-то добровольно предлагал свое время и пытался найти лучшее место для него, вместо того, чтобы просто закрывать его (что было бы допустимым вариантом, так как это не по теме для Code Review).
Яннис

2
Пожалуйста, не кросспост, либо. Вы делаете беспорядок, мы должны убрать.
Сорвано

Ответы:


7

У меня есть пара проблем:

  1. Я хотел бы убедиться, что вам действительно нужен общий дизайн перед его внедрением. Вы уверены, что вам понадобятся другие типы файлов, кроме XML? Если нет, зачем код для них? Если вам это в конечном итоге понадобится, вы можете в этот момент модифицировать свой код. Это не займет много времени, у вас, вероятно, будут другие требования, которые приведут к тому, что код будет отличаться от того, что вы предлагаете в настоящее время, и вам, вероятно, никогда не придется его писать. Как говорится, ЯГНИ (Тебе это не нужно).
  2. Если вам действительно нужен общий дизайн, и вы в этом совершенно уверены, то я бы сказал, что Parser<T>это в основном звук. Я вижу две потенциальные проблемы: (1) он предполагает ввод файла - что, если вы пытаетесь проанализировать поток JSON, полученный, например, из ответа HTTP? и (2) он не обязательно обеспечивает большую ценность, за исключением того, что является частью более крупной универсальной структуры, где у вас есть много разных типов синтаксических анализаторов для множества разных типов данных. Но я не уверен, что вам нужны такие большие общие рамки. Насколько я могу судить, сейчас у вас есть очень простой, конкретный вариант использования: разобрать файл XML в список ProductDatas.
  3. Это почти никогда не хорошая идея, чтобы проглотить исключения, как вы делаете в ProductDataXmlParser. Я бы преобразовал это в какой-то тип RuntimeException.

1
Мы создаем продукт, который будет взаимодействовать со многими внешними системами, поэтому, я думаю, было бы неплохо учесть любой тип файлов / формат ввода. Отличное замечание о JSON Stream. Именно поэтому мой метод синтаксического анализа в интерфейсе Parser принял параметр String вместо параметра File. В моем ProductDataXmlParser произошла небольшая ошибка, которую я исправил (необходимо передать файл в анализатор XmlBean). Вы также правы по поводу глотания исключений. Я быстро записал этот код в eclipse, чтобы продемонстрировать мой дизайн на стеке через пример;)
CKing

Ладно, круто. Я думаю, я бы сделал параметр Parser InputStream вместо String, это то, что я говорю. :) И приятно слышать об исключении - я не был уверен, вырезано ли оно из вашего фактического кода или просто пример кода для StackOverflow.

1
Кроме того, что касается создания продукта, который будет взаимодействовать со многими внешними системами, я бы не стал создавать общий код без конкретных требований. Например, до тех пор, пока у вас не будет хотя бы двух типов объектов для анализа или двух форматов файлов, которые вам нужны, я бы не стал создавать общий интерфейс Parser.

Я подумаю над тем, что вы говорите. Я хотел бы отметить, что существует 4 различных XML-файла, содержащих 4 различных типа данных, которые нужно проанализировать. Данные о продукте - это только один тип данных, которые используются нашей системой / продуктом.
CKing

У меня есть еще один вопрос к вам. Я не собираюсь использовать контекст, который является частью шаблона стратегии. Это будет хорошо? Я также избавляюсь от общих параметров и возвращаю Object в методе parse в интерфейсе Parser. Это делается для того, чтобы избежать использования классов, которые используют Parser, чтобы объявить его с параметром типа.
CKing

1

Ваш дизайн не лучший вариант. По твоему замыслу единственный способ его использования:

ProductDataXMLTYPE parser = new ProductDataXmlParser<ProductDataXMLTYPE>().parse(input); 
ProductDataTextTYPE parser = new ProductDataTextParser<ProductDataTextTYPE >().parse(input);

Мы не видим слишком много пользы от приведенного выше примера. Мы не можем делать такие вещи:

Parser parser = getParser(string parserName);
parser.parse();

Вы можете рассмотреть следующие два варианта, прежде чем искать универсальный:

  • 1, тот же вывод после разбора

Независимо от источника данных, данные о продукте будут иметь одинаковый формат перед сохранением в базе данных. Это контракт между клиентом и вашим сервисом. Поэтому я предполагаю, что у вас есть тот же ProductData, что и на выходе. Вы можете просто определить интерфейс:

public interface Parser {
    public ProductData parse(String inputFile);
}

Более того, вы определяете ProductData как интерфейс, если хотите, чтобы он был более гибким.

Если вы не хотите, чтобы парсер смешивался с данными. Вы можете разделить его на два интерфейса:

public interface Parser {
     public void parse(String inputFile);
}
public interface Data {
    public ProductData getData();
}

И ваш парсер будет выглядеть так:

public class XMLParser implements Parser, Data {} 
public class TextParser implements Parser, Data {}
  • 2, другой вывод после разбора

Если ProductData не похожи, и вы хотите повторно использовать интерфейс Parser. Вы можете сделать это следующим образом:

public interface Parser {
   public void parse(String inputFile);
}

class XMLParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataXML getProductData();        
}

class TextParse implements {
      @Override
      public void parse(String inputFile);

      ProductDataText getProductData();        
}

-2

На всякий случай, если вы предпочитаете использовать что-то уже доступное, я создал библиотеку java под названием JRecordBind , основанную на XMLSchema (при поддержке JAXB).

Он был создан для того, чтобы потреблять / производить файлы фиксированной длины, и, поскольку XMLSchema определяет их структуру, вы можете использовать его с простым JAXB для маршалирования / деинсталляции XML-файлов.


Я ищу дизайн для реализации универсального парсера! Я не думаю, что вы правильно поняли мой вопрос. :)
CKing
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.