избежать дублирования кода - PullRequest
2 голосов
/ 07 апреля 2011

рассмотрим следующий код:

if (matcher1.find()) {
   String str = line.substring(matcher1.start()+7,matcher1.end()-1);
   /*+7 and -1 indicate the prefix and suffix of the matcher... */    
   method1(str);
}
if (matcher2.find()) {
   String str = line.substring(matcher2.start()+8,matcher2.end()-1);
   method2(str);
}
...

У меня есть n сопоставителей, все сопоставители независимы (если одно истинно, оно ничего не говорит о других ...), для каждого сопоставителя, который является истинным -Я использую другой метод для сопоставляемого контента.
вопрос: Мне не нравится здесь ни дублирование кода, ни "магические числа", но мне интересно, есть ли лучший способ сделать это ...?(может быть Шаблон посетителя?) Есть предложения?

Ответы [ 4 ]

4 голосов
/ 07 апреля 2011

Создайте абстрактный класс и добавьте смещение в подкласс (с обработкой строк тоже ... в зависимости от ваших требований).

Затем заполните их в списке и обработайте список.

Вот пример процессора absract:

public abstract class AbsractProcessor {

    public void find(Pattern pattern, String line) {
        Matcher matcher = p.matcher(line);
        if (matcher.find()) {
            process(line.substring(matcher.start() + getStartOffset(), matcher.end() - getEndOffset()));
        }
    }

    protected abstract int getStartOffset();

    protected abstract int getEndOffset();

    protected abstract void process(String str);

}
1 голос
/ 07 апреля 2011

Просто пометьте часть регулярного выражения, которую вы хотите передать методу, с помощью группы захвата.

Например, если ваше регулярное выражение равно foo.*bar и вас не интересуют foo или bar, сделайте регулярное выражение foo(.*)bar.Затем всегда выбирайте группу 1 из Matcher.

Ваш код будет выглядеть следующим образом:

method1(matcher1.group(1));
method2(matcher2.group(2));
...

Еще одним шагом будет замена ваших методов классами, реализующими подобное:

public interface MatchingMethod {
  String getRegex();
  void apply(String result);
}

Тогда вы можете легко автоматизировать задачу:

for (MatchingMethod mm : getAllMatchingMethods()) {
  Pattern p = Pattern.compile(mm.getRegex());
  Matcher m = p.matcher(input);
  while (m.find()) {
    mm.apply(m.group(1));
}

Обратите внимание, что если производительность важна, то предварительная компиляция Pattern может улучшить время выполнения, если вы примените это кмного входов.

0 голосов
/ 07 апреля 2011

использовать решение Кочарда в сочетании с фабрикой (оператор switch) со всеми методами methodX. так что вы можете назвать это так:

Factory.CallMethodX(myEnum.MethodX, str)

вы можете назначить myEnum.MethodX на этапе заполнения решения Кочарда

0 голосов
/ 07 апреля 2011

Вы могли бы сделать это немного короче, но я задаюсь вопросом, действительно ли это стоит усилий:

private String getStringFromMatcher(Matcher matcher, int magicNumber) {
   return line.subString(matcher.start() + magicNumber, matcher.end() - 1 )
}

if (matcher1.find()) {
method1(getStringFromMatcher(matcher1, 7);
}

if (matcher2.find()) {
method2.(getStringFromMatcher(mather2, 8);
}
...