enericObjectPoolConfig();
poolConfig.setMaxTotal(globalConfig.getCacheMaxTotal());
poolConfig.setMaxWaitMillis(globalConfig.getMaxWaitMillis());
return new GenericObjectPool<Script>(new ScriptPoolFactory(script), poolConfig);
}
});
logger.info("success init scripts cache.");
}
public Object exec(String scriptPassed, Binding binding) {
GenericObjectPool<Script> scriptPool = null;
Script script = null;
try {
scriptPool = scriptCache.get(scriptPassed);
script = scriptPool.borrowObject();
script.setBinding(binding);
Object value = script.run();
script.setBinding(null);
return value;
} catch (Exception ex) {
logger.error("exxec script error: " + ex.getMessage(), ex);
return null;
} finally {
if (scriptPool != null && script != null) {
scriptPool.returnObject(script);
}
}
}
}
规则引擎方案
按钮条件逻辑和规则集合非常相似,可以考虑采用一款轻量级的规则引擎。通过配置平台来管理按钮逻辑规则。
可参阅 Java Drools5.1 规则流基础【示例】。当然,这里若选择 Java Drools 显然“重”了,可选用一款轻量级的Java开源规则引擎作为起点。
条件表达式
对于轻量级判断逻辑,采用条件表达匹配。条件表达匹配,实质是规则引擎的超轻量级实现。
优点: 超轻量级
不足: 可能不够灵活应对各种复杂场景。
思路
分析按钮方法的逻辑,可以看出它遵循一个套路:
ifMatchX-ReturnRx, ifMatchY-ReturnRy, ifMatchZ-ReturnRz, Else-ReturnDefault.
ifMatchX-ReturnRx 可以抽象成对象 (left:(field, op, value), right:result) ,其中 field 的值从传入的参数对象 valueMap 获取。 MatchX 既可能是原子条件,也可能是组合条件(与逻辑)。
原子条件的运算符主要包含 等于 eq, 不等于 neq , 包含 in , 大于 gt ,小于 lt , 大于或等于 gte, 小于或等于 lte 。
代码实现
STEP1: 定义条件测试接口 ICondition
public interface ICondition {
/**
* 传入的 valueMap 是否满足条件对象
* @param valueMap 值对象
* 若 valueMap 满足条件对象,返回 true , 否则返回 false .
*/
boolean satisfiedBy(Map<String,Object> valueMap);
/**
* 获取满足条件时要返回的值
*/
Boolean getResult();
}
STEP2: 基本条件的测试实现
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
@Data
public class BaseCondition {
protected String field;
protected CondOp op;
protected Object value;
public BaseCondition() {}
public BaseCondition(String field, CondOp op, Object value) {
this.field = field;
this.op = op;
this.value = value;
}
public boolean test(Map<String, Object> valueMap) {
try {
Object passedValue = valueMap.get(field);
switch (this.getOp()) {
case eq:
return Objects.equals(value, passedValue);
case neq:
return !Objects.equals(value, passedValue);
case lt:
// 需要根据格式转换成相应的对象然后 compareTo
return ((Comparable)passedValue).compareTo(value) < 0;
case gt:
return ((Comparable)passedValue).compareTo(value) > 0;
case lte:
return ((Comparable)passedValue).compareTo(value) <= 0;
case gte:
return ((Comparable)passedValue).compareTo(value) >= 0;
case in:
return ((Collection)value).contains(passedValue);
default:
return false;
}
} catch (Exception ex) {
return false;
}
}
}
STEP3: 按钮逻辑是单个条件实现
package zzz.study.patterns.composite.button;
import com.alibaba.fastjson.JSON;
import java.util.Map;
import lombok.Data;
@Data
public class SingleCondition implements ICondition {
private BaseCondition cond;
private Boolean result;
public SingleCondition() {
}
public SingleCondition(String field, CondOp condOp, Object value, boolean result) {
this.cond = new BaseCondition(field, condOp, value);
this.result = result;
}
pu