【发布时间】:2021-04-11 17:42:48
【问题描述】:
我必须执行以下任务。为简单起见,我创建了下表:
我们有输入和带有定义规则的表格。如果任何规则与此输入匹配,则对其应用操作。
例如输入HBC1234:
- starts_with H => true。
- 因此,将matching_value (H) 替换为
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。
【问题讨论】:
-
为什么你认为它违反了开闭原则?
cases 会考虑添加吗? -
@GyuHyeonChoi 谁知道。未来会添加哪些要求/条件始终是不可预测的。
-
如果有新的需求,修改代码不是可以避免的吗?我认为您的代码可以始终如一地添加规则并满足要求。
-
“替换操作”的抽象真的有必要吗? “remove”和“replace with an empty string”没有区别,反正就是携带字符串。
-
@Holger 拍得好
标签: java java-8 functional-programming