问题描述
|
我有以下代码(为示例简化):
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;
}
...
}
这些模式都是该类的静态最终成员。
所以我有很多模式,我想为每行找出是否与它们中的一个匹配,如果有,那就做点什么(随模式而变化)。您能想到一种以某种方式很好地重构此方法的方法吗?也许是我浏览过的一组模式(然后,如果匹配则如何知道该怎么办?)或其他一些想法。
解决方法
因为到目前为止还没有人回答,所以我会,尽管我不懂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语法时。。。
,我最终以以下方式重构。我创建了一个类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;
}
我不喜欢我必须抛弃所有获得的东西,但这是到目前为止找到的最好的解决方案。
,好的,这是我的简短答案:这不是语言问题,到目前为止,此处的答案和评论都离谱。所有语言,无论多么残酷,都包括类型。这是一个有关如何检测那些类型,然后采取行动调用相应的相应行动的问题。答案是来自四本书的两个模式。
首先,对于解析部分,我建议您将其视为中介者。动作对模式或文件一无所知,同样,动作的知识也不应注入触发上下文中。您可以将其称为解析器,检测器等,但是该类的核心将是模式到适当动作的映射。
在操作方面,使用的模式当然是Command模式。使用命令时有很多可能性。如果不需要上下文,那么命令非常简单,它只有一个execute方法。如果您需要传达一些将要更改的上下文,则可以对命令进行模板化或即时创建新命令,然后调用它们。