我有一个xml文件,其中包含要根据元数据JSON 和值数据JSON 输入进行检查的条件。
示例元数据JSON输入可以
{
"max_cash":789,
"min_cash":12,
"start_date":"28 Oct 2018",
"end_date":"02 Dec 2018",
"allowed_cities":"3,4,5,6"
}
样本值数据JSON可以
{
"cash":34,
"order_date":"03 Nov 2018",
"city_id":"5,4"
}
每个条件都可以构成一个表达式,并具有以下属性
示例xml如下
<condtion id="1" param_type="NUMBER" param_holder="max_cash" operator=">=" param_value_holder="cash" next_condition="2"></condtion>
<condtion id="2" param_type="NUMBER" param_holder="min_cash" operator="<=" param_value_holder="cash" next_condition="3"></condtion>
<condtion id="3" param_type="DATE" param_holder="start_date" operator="<=" param_value_holder="order_date" next_condition="4"></condtion>
<condtion id="4" param_type="DATE" param_holder="end_date" operator=">=" param_value_holder="order_date" next_condition="5"></condtion>
<condtion id="5" param_type="LIST" param_holder="allowed_cities" operator="CONTAINS" param_value_holder="city_id" next_condition="-1">
我正在使用JAVA,这里几乎所有内容都是动态的,可以随时添加,修改和删除。将来可能还会有更多的运算符,数据类型等。 我正在寻找一种解决方案,使人们可以添加任何条件而无需重新部署代码。仅当元数据JSON更改时,才应进行代码部署。 我读到有关ANTLR的文章,它认为这将使解决方案无效,并且语法和解析器的创建和维护对开发人员来说是开销。 我用Factory Pattern提出了另一种解决方案,其中Operator工厂将输入作为操作符,并返回相应的Operator对象,该对象进一步将左项,右项和参数类型作为参数,并根据特定的参数类型评估条件。
public abstract class Operator {
public abstract boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException;
}
public class GTEOperator extends Operator {
@Override
public boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException {
switch (param_type)
{
case "DATE":
return new SimpleDateFormat().parse(leftTerm).after(new SimpleDateFormat().parse(rightTerm));
case "NUMBER":
return Integer.parseInt(leftTerm) >=Integer.parseInt(rightTerm);
default:
return true;
}
}
}
public class ContainsOperator extends Operator {
@Override
public boolean evaluate(String leftTerm, String rightTerm, String param_type) throws ParseException {
return Arrays.asList(leftTerm.split(",")).contains(rightTerm);
}
}
此解决方案不是动态的,并且涉及大量代码重写。 有人可以用一种更好的,可扩展的和面向对象的方法来帮助我。
答案 0 :(得分:0)
在这里我建议一些更明智的功能性方法。
首先,摆脱next_condition
。由于附加功能是可交换的(即booleanValue1 && boleanValue2
始终等于booleanValue2 && booleanValue1
),因此您根本不在乎评估的特定顺序。
其次,您最好将每个条件映射到a ..谓词。函数,使用要验证的对象,并在最简单的情况或更复杂的情况下返回单个true/false
(例如一系列有意义的错误以及您可能需要的任何麻烦)。
只要有了这些谓词,就可以将它们自由合并(减少,折叠,聚合-本质上相同的功能有很多名称)将它们合并为一个:决定,您是否愿意懒惰或急切的评估策略,要么生成另一个谓词,要么即时计算它们,然后吐出结果布尔值。因此,您的“客户代码”接收到一个ToBeValidateObject -> Boolean
函数,很好地封装了所有底层细节。
最后,您肯定需要某种工厂才能根据指定的操作类型来产生有效的谓词。那就是您的主要扩展点:引入新的运算符或重新定义旧的运算符应该与修改Factory.Create(...)
方法一样简单。确保有IFactory
接口以避免静态不可单元测试的代码依赖关系。在内部,它可能像HashTable一样简单,由适当的字符串/字符数组作为键。
希望有帮助。让我知道是否需要更多代码示例。