简体   繁体   English

避免代码重复

[英]avoid code duplication

consider the following code: 考虑以下代码:

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);
}
...

I have n matchers, all matchers are independent (if one is true, it says nothing about the others...), for each matcher which is true - I am invoking a different method on the content it matched. 我有n个匹配器,所有匹配器都是独立的(如果一个匹配器是正确的,则对其他匹配器什么也没有说...),对于每个匹配器,这都是正确的-我正在对匹配的内容调用不同的方法。
question: I do not like the code duplication nor the "magic numbers" in here, but I'm wondering if there is better way to do it...? 问题:我不喜欢这里的代码重复或“魔术数字”,但是我想知道是否有更好的方法...? (maybe Visitor Pattern?) any suggestions? (也许是访客模式?)有什么建议吗?

Create an abstract class, and add offset in subclass (with string processing too... depending of your requirement). 创建一个抽象类,并在子类中添加偏移量(也可以进行字符串处理……取决于您的要求)。

Then populate them in a list and process the list. 然后将它们填充在列表中并处理该列表。

Here is a sample absract processor: 这是一个示例抽象处理器:

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);

}

Simple mark the part of the regex that you want to pass to the method with a capturing group. 使用捕获组简单标记要传递给方法的正则表达式部分。

For example if your regex is foo.*bar and you are not interested in foo or bar , make the regex foo(.*)bar . 例如,如果您的正则表达式为foo.*bar而您对foobar不感兴趣,请将正则表达式设为foo(.*)bar Then always grab the group 1 from the Matcher . 然后,始终从Matcher抓取组1。

Your code would then look like this: 您的代码将如下所示:

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

One further step would be to replace your methods with classes implementing an like this: 下一步将用实现如下所示的类替换您的方法:

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

Then you can easily automate the task: 然后,您可以轻松地自动化任务:

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

Note that if performance is important, then pre-compiling the Pattern can improve runtime if you apply this to many inputs. 请注意,如果性能很重要,那么如果将它应用于许多输入,则预编译Pattern可以改善运行时。

You could make it a little bit shorter, but I the question is, is this really worth the effort: 您可以将其缩短一点,但是我的问题是,这真的值得努力吗:

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);
}

use Cochard's solution combined with a factory (switch statement) with all the methodX methods. 将Cochard的解决方案与工厂(switch语句)与所有methodX方法结合使用。 so you can call it like this: 因此您可以这样称呼它:

Factory.CallMethodX(myEnum.MethodX, str)

you can assign the myEnum.MethodX in the population step of Cochard's solution 您可以在Cochard解决方案的填充步骤中分配myEnum.MethodX

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM