2011-04-15 65 views
2

我有下面的代碼段(縮短爲例子):重構模式匹配的序列

while (reader.ready()) { 
    String line = reader.readLine(); 

    Matcher responseCodeMatcher = responseCodePattern.matcher(line); 
    if (responseCodeMatcher.matches()) { 
     responseCode = Integer.parseInt(responseCodeMatcher.group(1)); 
     continue; 
    } 

    Matcher cacheControlMatcher = cacheControlPattern.matcher(line); 
    if (cacheControlMatcher.matches()) { 
     cacheControl = CacheControl.parseString(responseCodeMatcher.group(1)); 
     continue; 
    } 

     ... 

} 

的模式是類的所有的靜態最終成員。 所以我有一堆模式,我想找出每一行,如果它匹配其中之一,如果是這樣 - 做一些事情(從模式到模式)。你能想出一種很好地重構這種方式嗎?也許是我過去的一系列模式(然後我怎麼知道如果匹配,該怎麼做?)或其他一些想法。

+2

僅供參考,'while(reader.ready())'不正確。 'ready()'方法告訴你Reader是否可以在不阻塞的情況下讀取更多*,而不是如果有更多的文本被讀取。一行一行的閱讀習慣是'while((line = reader.readLine())!= null)'。 – 2011-04-15 15:02:51

回答

2

我以如下方式結束了重構。我創建了一個類HttpPatterns

package cs236369.proxy.types; 

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public enum HttpPatterns { 
    RESPONSE_CODE("^HTTP/1\\.1 (\\d+) .*$"), 
    CACHE_CONTROL("^Cache-Control: (\\w+)$"), 
    HOST("^Host: (\\w+)$"), 
    REQUEST_HEADER("(GET|POST) ([^\\s]+) ([^\\s]+)$"), 
    ACCEPT_ENCODING("^Accept-Encoding: .*$"), 
    CONTENT_ENCODING("^Content-Encoding: ([^\\s]+)$"); 

    private final Pattern pattern; 

    HttpPatterns(String regex) { 
     pattern = Pattern.compile(regex); 
    } 

    public boolean matches(String expression) { 
     return pattern.matcher(expression).matches(); 
    } 

    public Object process(String expression) { 
     Matcher matcher = pattern.matcher(expression); 
     if (!matcher.matches()) { 
      throw new RuntimeException("Called `process`, but the expression doesn't match. Call `matches` first."); 
     } 

     if (this == RESPONSE_CODE) { 
      return Integer.parseInt(matcher.group(1)); 
     } else if (this == CACHE_CONTROL) { 
      return CacheControl.parseString(matcher.group(1)); 
     } else if (this == HOST) { 
      return matcher.group(1); 
     } else if (this == REQUEST_HEADER) { 
      return new RequestHeader(RequestType.parseString(matcher.group(1)), matcher.group(2), matcher.group(3)); 
     } else if (this == CONTENT_ENCODING) { 
      return ContentEncoding.parseString(matcher.group(1)); 
     } else { //never happens 
      return null; 
     } 
    } 


} 

我用它像這樣:

String line; 
      while ((line = reader.readLine()) != null) { 

       if (HttpPatterns.CACHE_CONTROL.matches(line)) { 
        cacheControl = (CacheControl) HttpPatterns.RESPONSE_CODE.process(line); 
       } else if (HttpPatterns.REQUEST_HEADER.matches(line)) { 
        requestHeader = (RequestHeader) HttpPatterns.REQUEST_HEADER.process(line); 
       } else if (HttpPatterns.HOST.matches(line)) { 
        requestHost = (String) HttpPatterns.HOST.process(line); 
       } else if (HttpPatterns.ACCEPT_ENCODING.matches(line)) { 
        continue; 
       } else if (line.isEmpty()) { 
        break; 
       } 
       fullRequest += "\r\n" + line; 
      } 

我不喜歡,我要投的一切,我得到的,但是這是我迄今爲止所發現的最佳解決方案。

2

因爲到目前爲止沒有人回答,我會,雖然我不知道Java。
在C#中我會創建一個元組列表。元組的項目1是要檢查的模式,項目2是一個匿名方法,它包含要執行的特定於模式的代碼。在C#中,它會是這個樣子:

var patterns = new List<Tuple<Pattern, Action<Matcher>>>(); 
patterns.Add(Tuple.Create(responseCodePattern, matcher => 
    { 
     responseCode = Integer.parseInt(matcher.group(1)); 
    })); 

patterns.Add(Tuple.Create(cacheControlPattern, matcher => 
    { 
     cacheControl = CacheControl.parseString(matcher.group(1)); 
    })); 

while (reader.ready()) { 
    String line = reader.readLine(); 
    foreach(var tuple in patterns) 
    { 
     Matcher matcher = tuple.Item1.matcher(line); 
     if(matcher.matches()) 
     { 
      tuple.Item2(matcher); 
      break; 
     } 
    } 
} 

我不知道,如果這使得任何意義,一個Java的傢伙,尤其是與lambda語法......請問,如果不是:-)

+0

在Java中,你需要編寫一個接口,如公共接口UseMatcher {match(Matcher matcher); }然後你需要爲每件事寫一個匿名的內部類。那麼你需要跳過一些箍環,因爲你只能訪問內部類中的最終變量。你可能最終會聲明像int [] responseCode = new int [1]和每個地方都使用responseCode [0]。總之這種方法在Java中有點痛苦:) – 2011-04-15 14:13:11

+0

@Jeff:真是可惜... – 2011-04-15 14:15:36

0

好的,這裏是我的簡短答案:這不是一個語言問題,迄今爲止的答案和評論都是非常熱門的。所有的語言,不管如何reprobate,包括類型。這是一個關於如何檢測這些類型然後執行適當的相應操作的問題。答案是來自四本書幫派的一些模式。

首先,對於解析部分,我建議您將其視爲中介。這些行爲應該對模式或文件一無所知,同樣,行爲的知識不應該被注入到觸發的上下文中。你可以稱它爲解析器,探測器等等,但是這個類的核心將會是這個模式映射到適當的動作。

在動作方面,使用的模式當然是Command模式。使用命令時有很多可能性。如果你不需要上下文,那麼這個命令非常簡單,它只是一個執行方法。如果你需要傳遞一些將要改變的上下文,你可以模擬這些命令或者隨時創建新的命令然後調用它們。