首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用组合设计模式分析工作经验长度

使用组合设计模式分析工作经验长度
EN

Code Review用户
提问于 2017-09-16 20:02:03
回答 1查看 138关注 0票数 0

我想得到一个数字从给定的文本(如果有),这是关于工作经验,在几个月。我认为这个数字是以几个月为单位的,比如在文本中写"27 miesięcy“、"27 miesiecy”或“27 miesiecy”,如果一个人写的是"3 lat“或”3 lat“。

ExperienceAlg0类主要负责这方面的工作。我想让它变得灵活和开放,可以添加另一个规则/算法“如何在文本中找到月数”。我试着使用复合设计模式。

算法运行良好,但是根据OOP和Bob叔叔的设计可以吗?

代码语言:javascript
复制
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);
    }
}
代码语言:javascript
复制
public interface ExperiencePattern {

    public int getPattern(String text);

}
代码语言:javascript
复制
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;
    }



}
代码语言:javascript
复制
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;
    }



}
代码语言:javascript
复制
public interface Algorithm <T> {

    public T calc(String textToLower);

}
代码语言:javascript
复制
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);
    }




}
代码语言:javascript
复制
import java.util.Comparator;
public class DescendingComparator implements Comparator<Integer>{

    @Override
    public int compare(Integer x1, Integer x2) {

        return x2 - x1;
    }



}
EN

回答 1

Code Review用户

发布于 2017-09-16 23:03:39

你写了这个:

代码语言:javascript
复制
    Pattern p = Pattern.compile("\\d+miesi[e|ę]cy|\\d+ miesi[e|ę]cy");

但更自然的是,不加改动地表达出来:

代码语言:javascript
复制
    Pattern p = Pattern.compile("\\d+\\s*miesi[e|ę]cy");

我想知道你是否想加入一个CASE_INSENSITIVE | UNICODE_CASE旗子。

代码语言:javascript
复制
public interface ExperiencePattern {

许多项目都会选择拼写这个IExperiencePattern

干-别重复了。奇怪的是,您有一对具有不同模式常量的复制n粘贴的相同类,而不是一个接受模式参数的类。

代码语言:javascript
复制
        tmp = tmp.replaceAll("\\D", "");

谢谢你教我“非数字”模式。但是,表达意图的更自然的方式是删除它,并在regex中添加一个捕获组:

代码语言:javascript
复制
    Pattern p = Pattern.compile("(\\d+)\\s*miesi[e|ę]cy");

然后Integer.parseInt(m.group(1))就会给你你想要的。

代码语言:javascript
复制
        if (x < 40) {
            result = x * 12;

好的,我想在一个直接重构中,您需要传递两个参数,一个模式和maxAcceptableValue。但是,最好还是坚持使用单个参数,让调用方进行范围检查。

代码语言:javascript
复制
public interface Algorithm <T> {

    public T calc(String textToLower);

这两种标识都是无可救药的模糊。请给绅士读者一条线索。另外,添加一些/** javadoc */也会有所帮助。

代码语言:javascript
复制
public ExperienceAlg0(List<ExperiencePattern> list){
    listPatterns = list;
}

在ctor中通常会明确提到"this":this.listPatterns = list;

代码语言:javascript
复制
    for(ExperiencePattern ep : listPatterns) {
        result.add(ep.getPattern(text));
    }

这太可爱了。但概括到确切的2例可能是在小的方面。而不是这个循环,我鼓励您将范围检查测试提升到这个位置,它将使用每个模式提供一对几乎相同的调用。

代码语言:javascript
复制
    Collections.sort(result, new DescendingComparator());
    return result.get(0);

这很酷。我喜欢它。非常干净的方式丢弃箔条。

根据OOP的说法,你问这个设计是否可以。如果在每个类的顶部添加一个句子的javadocs,说明该类的单个责任,特别是对任何接口类,这将更容易评估。例如,这将帮助读者确定范围检查属于哪一层。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/175837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档