在MeteorTL([url]http://www.meteortl.org[/url])中,多处遇到需要按类型分派处理,如:BinaryOperatorHandler,UnaryOperatorHandler,PropertyHandler,OutputFormatter,StringSequence等,
以BinaryOperatorHandler为例:
当引擎遇到二元操作符会回调BinaryOperatorHandler进行求值,接口如下:
但有的操作符是重载的,
如:加号(+),在操作数为“数字”和“字符串”时要进行不同的操作,
1.最直接的实现方法是使用instanceof逐个判断,但其可扩展性极差,实现如下:
2.职责链模式,每个Handler持有下一个Handler的引用,实现如下:
3. 用一个包装类,注册相应类型的处理类,实现如下:
以BinaryOperatorHandler为例:
当引擎遇到二元操作符会回调BinaryOperatorHandler进行求值,接口如下:
public interface BinaryOperatorHandler extends OperatorHandler {
// 传入操作数,返回求值结果
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException;
}
但有的操作符是重载的,
如:加号(+),在操作数为“数字”和“字符串”时要进行不同的操作,
1.最直接的实现方法是使用instanceof逐个判断,但其可扩展性极差,实现如下:
public class AddBinaryOperatorHandler implements BinaryOperatorHandler {
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
if (leftOperand instanceof Integer && leftOperand instanceof Integer)
return new Integer(((Integer)leftOperand).intValue()
+ ((Integer)rightOperand).intValue());
/* 如果要添加一个日期加法,就需要修改代码加入else if
else if (leftOperand instanceof Date && leftOperand instanceof DateNumber)
return new Date(((Date)leftOperand).getTime()
+ ((DateNumber)rightOperand).getTime());*/
else
return String.valueOf(leftOperand) + String.valueOf(rightOperand);
}
}
2.职责链模式,每个Handler持有下一个Handler的引用,实现如下:
public abstract class BinaryOperatorHandlerChain implements BinaryOperatorHandler {
private BinaryOperatorHandler nextHandler;
protected BinaryOperatorHandler getNextHandler() {
return nextHandler;
}
public void setNextHandler(BinaryOperatorHandler nextHandler) {
this.nextHandler = nextHandler;
}
}
public class IntegerAddBinaryOperatorHandler extends BinaryOperatorHandlerChain {
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
if (leftOperand instanceof Integer && leftOperand instanceof Integer)
return new Integer(((Integer)leftOperand).intValue()
+ ((Integer)rightOperand).intValue());
return getNextHandler().doEvaluate(leftOperand, rightOperand);
}
}
public class StringAddBinaryOperatorHandler extends BinaryOperatorHandlerChain {
// @overwrite
public void setNextHandler(BinaryOperatorHandler nextHandler) {
throw new ConfigurationException("字符串相加为终结处理,不能有下一Handler!");
}
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
return String.valueOf(leftOperand) + String.valueOf(rightOperand);
}
}
3. 用一个包装类,注册相应类型的处理类,实现如下:
public class BinaryOperatorHandlerDispatcher implements BinaryOperatorHandler {
private final Map matchHandlers; //类型为<BinaryOperandMatcher, BinaryOperatorHandler>
private final BinaryOperatorHandler defaultHandler;
public BinaryOperatorHandlerDispatcher(Map matchHandlers, BinaryOperatorHandler defaultHandler) {
this.matchHandlers = matchHandlers;
this.defaultHandler = defaultHandler;
}
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
// 在集合中匹配相应类型的处理器
for (Iterator iterator = matchHandlers.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry)iterator.next();
if (((BinaryOperandMatcher)entry.getKey()).isMatch(leftOperand, rightOperand))
return ((BinaryOperatorHandler)entry.getValue()).doEvaluate(leftOperand, rightOperand);
}
// 未找到相应类型的处理器则使用默认处理器
if (defaultHandler != null)
return defaultHandler.doEvaluate(leftOperand, rightOperand);
//否则抛出异常
throw new UnhandleException("没有找到相应处理类!");
}
}
public class BinaryOperandMatcher {
private final Class leftOperandClass;
private final Class rightOperandClass;
public BinaryOperandMatcher(Class leftOperandClass, Class rightOperandClass) {
this.leftOperandClass = leftOperandClass;
this.rightOperandClass = rightOperandClass;
}
// 匹配操作数类型
public boolean isMatch(Object leftOperand, Object rightOperand) {
return isMatchClass(leftOperand, leftOperandClass) && isMatchClass(rightOperand, rightOperandClass);
}
private boolean isMatchClass(Object operand, Class operandClass) {
if (operandClass == null || operand == null)
return operandClass == null && operand == null;
return operandClass.isAssignableFrom(operand.getClass());
}
}
public class IntegerAddBinaryOperatorHandler implements BinaryOperatorHandler {
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
assert(leftOperand instanceof Integer && leftOperand instanceof Integer);
return new Integer(((Integer)leftOperand).intValue() + ((Integer)rightOperand).intValue());
}
}
public class StringAddBinaryOperatorHandler implements BinaryOperatorHandler {
public Object doEvaluate(Object leftOperand, Object rightOperand)
throws ExpressionException {
return String.valueOf(leftOperand)
+ String.valueOf(rightOperand);
}
}