PYTANIE
Klasa PatternOption1
i PatternOption2
są prawie takie same. Jak to zmienić by było mniej powtórzeń?
Jedyne co mi przychodzi do głowy to zrobić dziedziczenie, ale podobno dziedziczenie jest złe.
Opis klas:
Test
- test jednostkowy, cel agorytmu. Algorytm wyszukuje w tekście liczby większe od 1000 zapisane w dziwnych formatach np. 7k zwróci 7000, 7.5 zwróci 7500.
Mother
- tworzy obiekt Engine
zasilając go różnymi MyPattern
, którego zachowanie jest określane przez obiekty implementujące IPatternOption
.
Engine
- silnik, przelatuje przez wszystkie MyPattern
i robi calculate()
KOD
import junit.framework.TestCase;
public class Test extends TestCase {
@org.junit.Test
public void testcalculate1() {
// Having:
String text = "Zarabiam 7k";
// When:
Mother m = new Mother();
Integer result = m.calculate(text);
// Then:
assertEquals(7000, result.intValue());
}
@org.junit.Test
public void testcalculate2() {
// Having:
String text = "Zarabiam 7.5k";
// When:
Integer result = new Mother().calculate(text);
// Then:
assertEquals(7500, result.intValue());
}
}
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Mother {
Engine engine;
public Mother() {
Set<IPattern> set = new HashSet<>();
set.add(new MyPattern("\\s\\d+k", new PatternOption1()));
set.add(new MyPattern("\\s\\d+[,|.]\\d+k", new PatternOption2()));
engine = new Engine(set);
}
public Integer calculate(String text) {
List<Integer> result = engine.calculate(text);
return result.stream().filter(p -> p != null).findFirst().orElse(null);
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class Engine {
Set<IPattern> patternRules;
public Engine(Set<IPattern> set){
this.patternRules = set;
}
public List<Integer> calculate(String text){
List<Integer> result = new ArrayList<>();
for (IPattern p : patternRules) {
result.add(p.getPattern(text));
}
return result;
}
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyPattern implements IPattern{
String regex;
IPatternOption predicate;
public MyPattern(String regex, IPatternOption predicate){
this.regex = regex;
this.predicate = predicate;
}
@Override
public Integer getPattern(String text) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
while (m.find()) {
String tmp = m.group();
tmp = tmp.replace(" ", "");
predicate.compile(tmp);
if (predicate.test()) {
return predicate.getValue(); // return first match
}
}
return null; // if there wasn't matched pattern
}
}
public interface IPatternOption {
public void compile(String t);
public boolean test();
public Integer getValue();
}
public class PatternOption1 implements IPatternOption{
private Integer number;
final private int MIN_NUMBER = 1000;
@Override
public void compile(String text) {
String tmp = text.replace("k", "");
int x = Integer.parseInt(tmp) * 1000;
this.number = x;
}
@Override
public boolean test() {
return number >= MIN_NUMBER;
}
@Override
public Integer getValue() {
return number;
}
}
public class PatternOption2 implements IPatternOption{
private Integer number;
final private int MIN_NUMBER = 1000;
@Override
public void compile(String text) {
String tmp = text.replace("k", "");
String[] partNumber = tmp.split("[,|.]");
int x = Integer.parseInt(partNumber[0]) * 1000 + Integer.parseInt(partNumber[1]) * 100;
this.number = x;
}
@Override
public boolean test() {
return number >= MIN_NUMBER;
}
@Override
public Integer getValue() {
return number;
}
}