我必须执行以下任务。为简单起见,我创建了下表:
我们有输入和一个定义了规则的表格。如果有任何规则与此输入匹配,则对其应用操作。
例如输入HBC1234
:
M
=> 结果为MBC1234
。以同样的方式迭代此输入的所有其他规则。
这是替换规则的实体:
@Data
@Entity
@NoArgsConstructor
public class ReplacementRule implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@NotNull
@Enumerated(EnumType.STRING)
private MatchingOperation matchingOperation;
@NotNull
private String matchingValue;
@NotNull
@Enumerated(EnumType.STRING)
private ReplacementOperation replacementOperation;
private String replacementValue;
}
以及此任务的实现:
private static String apply(ReplacementRule rule, String plateNumber) {
switch (rule.getMatchingOperation()) {
case STARTS_WITH:
if (plateNumber.startsWith(rule.getMatchingValue())) {
return switch (rule.getReplacementOperation()) {
case REPLACE -> plateNumber.replaceFirst(rule.getMatchingValue(), rule.getReplacementValue());
case REMOVE -> plateNumber.substring(rule.getMatchingValue().length());
};
}
case CONTAINS:
if (plateNumber.contains(rule.getMatchingValue())) {
return switch (rule.getReplacementOperation()) {
case REPLACE -> plateNumber.replaceAll(rule.getMatchingValue(), rule.getReplacementValue());
case REMOVE -> plateNumber.replaceAll(rule.getMatchingValue(), "");
};
}
case ENDS_WITH:
if (plateNumber.endsWith(rule.getMatchingValue())) {
return switch (rule.getReplacementOperation()) {
case REPLACE -> plateNumber.substring(0, getEndIndex(rule, plateNumber)).concat(rule.getReplacementValue());
case REMOVE -> plateNumber.substring(0, getEndIndex(rule, plateNumber));
};
}
case EQUALS:
if (plateNumber.equals(rule.getMatchingValue())) {
return switch (rule.getReplacementOperation()) {
case REPLACE -> rule.getReplacementValue();
case REMOVE -> "";
};
}
}
return "";
}
private static int getEndIndex(ReplacementRule rule, String plateNumber) {
return plateNumber.length() - rule.getMatchingValue().length();
}
最终用法如下:
public Optional<WhiteList> checkReplacementRules(String plateNumber) {
List<ReplacementRule> allRules = ruleRepository.findAll();
Optional<WhiteList> result = Optional.empty();
for (ReplacementRule rule : allRules) {
String newPlate = transform(rule, plateNumber);
if (StringUtils.isNotBlank(newPlate)) {
result = whiteListRepository.findByNumberPlate(newPlate);
}
}
return result;
}
它结合了匹配和逻辑以在一种方法 apply()
中进行替换。然而,它违反了Open-Closed Principle。但它有效。尽管解决方案并不是最好的。
似乎这种任务符合函数式编程概念。
如何将其重新设计为函数式风格?
Java 版本为 15。
答案 0 :(得分:2)
让 enum
类实现动作,即操作。
Regex 似乎非常适合您正在做的事情。
private static String apply(ReplacementRule rule, String plateNumber) {
String regex = rule.getMatchingOperation().regexFor(rule.getMatchingValue());
String replacement = rule.getReplacementOperation().regexFor(rule.getReplacementValue());
return Pattern.compile(regex)
.matcher(plateNumber)
.replaceFirst(replacement);
}
public enum MatchingOperation {
STARTS_WITH(v -> "^" + Pattern.quote(v)),
CONTAINS (v -> Pattern.quote(v)),
ENDS_WITH (v -> Pattern.quote(v) + "$"),
EQUALS (v -> "^" + Pattern.quote(v) + "$");
private final UnaryOperator<String> asRegex;
private MatchingOperation(UnaryOperator<String> asRegex) {
this.asRegex = asRegex;
}
public String regexFor(String matchingValue) {
return this.asRegex.apply(matchingValue);
}
}
public enum ReplacementOperation {
REPLACE(Matcher::quoteReplacement),
REMOVE (v -> "");
private final UnaryOperator<String> asRegex;
private ReplacementOperation(UnaryOperator<String> asRegex) {
this.asRegex = asRegex;
}
public String regexFor(String replacementValue) {
return this.asRegex.apply(replacementValue);
}
}
答案 1 :(得分:0)
我不认为您的设计违反了开闭原则,但是,这是我的实现。由于它可以将未来的需求添加为功能,因此可以称为功能性。
@FunctionalInterface
interface Rule {
public String apply(String string);
}
Rule
用于每个需求的函数。
class Replacement {
ArrayList<Rule> rules = new ArrayList<Rule>();
public Replacement addRule(Rule rule) {
rules.add(rule);
return this;
}
public String applyAll(String string) {
System.out.printf("%s --> ", string);
for (Rule rule : rules) {
string = rule.apply(string);
}
System.out.println(string);
return string;
}
}
Replacement
可以对输入进行 addRule
和 applyAll
规则。
以下是如何将 Rule
添加为函数并应用:
public class Main {
public static void main(String[] args) {
Replacement r = new Replacement()
.addRule((String string) -> {
if (string.startsWith("H"))
return "M" + string.substring(1);
return string;
})
.addRule((String string) -> {
return string.replaceAll("A", "");
})
.addRule((String string) -> {
if (string.endsWith("8"))
return string.substring(0, string.length() - 1);
return string;
})
.addRule((String string) -> {
if (string.equals("ABC12B467"))
return "ABC123467";
return string;
});
r.applyAll("HBC1234");
r.applyAll("ABC1234");
r.applyAll("ABC9988");
r.applyAll("ABC12B467");
}
}