我想得到一个数字从给定的文本(如果有),这是关于工作经验,在几个月。我认为这个数字是以几个月为单位的,比如在文本中写"27 miesięcy“、"27 miesiecy”或“27 miesiecy”,如果一个人写的是"3 lat“或”3 lat“。
ExperienceAlg0类主要负责这方面的工作。我想让它变得灵活和开放,可以添加另一个规则/算法“如何在文本中找到月数”。我试着使用复合设计模式。
算法运行良好,但是根据OOP和Bob叔叔的设计可以吗?
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import junit.framework.TestCase;
public class TestExperienceAlg0 extends TestCase {
/*
**
** this test class unit test show how app works
**
*/
@Test
public void testCalc1() {
// Given:
String text = "programuję od 5 lat.";
// When:
List<ExperiencePattern> patternList = new ArrayList<>();
patternList.add(new ExperiencePatternMonths());
patternList.add(new ExperiencePatternYears());
ExperienceAlg0 alg = new ExperienceAlg0(patternList);
int result = alg.calc(text);
// Then:
assertEquals(0, result);
}
}public interface ExperiencePattern {
public int getPattern(String text);
}import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExperiencePatternMonths implements ExperiencePattern{
@Override
public int getPattern(String text) {
int result = 0;
Pattern p = Pattern.compile("\\d+miesi[e|ę]cy|\\d+ miesi[e|ę]cy");
Matcher m = p.matcher(text);
while (m.find()) {
String tmp = m.group();
tmp = tmp.replaceAll("\\D", "");
int x = Integer.parseInt(tmp);
if (x < (40 * 12)) { // assuming that the max experience is 40
// years.
result = x;
;
}
}
return result;
}
}import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExperiencePatternYears implements ExperiencePattern{
@Override
public int getPattern(String text) {
int result = 0;
Pattern p = Pattern.compile("\\d+lat|\\d+ lat");
Matcher m = p.matcher(text);
while (m.find()) {
String tmp = m.group();
tmp = tmp.replaceAll("\\D", "");
int x = Integer.parseInt(tmp);
if (x < 40) { // assuming that the max experience is 40 years.
result = x * 12;
}
}
return result;
}
}public interface Algorithm <T> {
public T calc(String textToLower);
}import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExperienceAlg0 implements Algorithm<Integer> {
List<ExperiencePattern> listPatterns;
public ExperienceAlg0(List<ExperiencePattern> list){
listPatterns = list;
}
@Override
public Integer calc(String text) {
List<Integer> result = new ArrayList<>();
for(ExperiencePattern ep : listPatterns){
result.add(ep.getPattern(text));
}
Collections.sort(result, new DescendingComparator());
return result.get(0);
}
}import java.util.Comparator;
public class DescendingComparator implements Comparator<Integer>{
@Override
public int compare(Integer x1, Integer x2) {
return x2 - x1;
}
}发布于 2017-09-16 23:03:39
你写了这个:
Pattern p = Pattern.compile("\\d+miesi[e|ę]cy|\\d+ miesi[e|ę]cy");但更自然的是,不加改动地表达出来:
Pattern p = Pattern.compile("\\d+\\s*miesi[e|ę]cy");我想知道你是否想加入一个CASE_INSENSITIVE | UNICODE_CASE旗子。
public interface ExperiencePattern {许多项目都会选择拼写这个IExperiencePattern。
干-别重复了。奇怪的是,您有一对具有不同模式常量的复制n粘贴的相同类,而不是一个接受模式参数的类。
tmp = tmp.replaceAll("\\D", "");谢谢你教我“非数字”模式。但是,表达意图的更自然的方式是删除它,并在regex中添加一个捕获组:
Pattern p = Pattern.compile("(\\d+)\\s*miesi[e|ę]cy");然后Integer.parseInt(m.group(1))就会给你你想要的。
if (x < 40) {
result = x * 12;好的,我想在一个直接重构中,您需要传递两个参数,一个模式和maxAcceptableValue。但是,最好还是坚持使用单个参数,让调用方进行范围检查。
public interface Algorithm <T> {
public T calc(String textToLower);这两种标识都是无可救药的模糊。请给绅士读者一条线索。另外,添加一些/** javadoc */也会有所帮助。
public ExperienceAlg0(List<ExperiencePattern> list){
listPatterns = list;
}在ctor中通常会明确提到"this":this.listPatterns = list;
for(ExperiencePattern ep : listPatterns) {
result.add(ep.getPattern(text));
}这太可爱了。但概括到确切的2例可能是在小的方面。而不是这个循环,我鼓励您将范围检查测试提升到这个位置,它将使用每个模式提供一对几乎相同的调用。
Collections.sort(result, new DescendingComparator());
return result.get(0);这很酷。我喜欢它。非常干净的方式丢弃箔条。
根据OOP的说法,你问这个设计是否可以。如果在每个类的顶部添加一个句子的javadocs,说明该类的单个责任,特别是对任何接口类,这将更容易评估。例如,这将帮助读者确定范围检查属于哪一层。
https://codereview.stackexchange.com/questions/175837
复制相似问题