重构按类型分派处理
在MeteorTL(http://www.meteortl.org)中,多处遇到需要按类型分派处理,如:BinaryOperatorHandler,UnaryOperatorHandler,PropertyHandler,OutputFormatter,StringSequence等,
以BinaryOperatorHandler为例:
当引擎遇到二元操作符会回调BinaryOperatorHandler进行求值,接口如下:
public interface BinaryOperatorHandler extends OperatorHandler {// 传入操作数,返回求值结果public Object doEvaluate(Object leftOperand, Object rightOperand)throws ExpressionException;}
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 ifelse if (leftOperand instanceof Date && leftOperand instanceof DateNumber)return new Date(((Date)leftOperand).getTime() + ((DateNumber)rightOperand).getTime());*/elsereturn String.valueOf(leftOperand) + String.valueOf(rightOperand);}}
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 {// @overwritepublic void setNextHandler(BinaryOperatorHandler nextHandler) {throw new ConfigurationException("字符串相加为终结处理,不能有下一Handler!");}public Object doEvaluate(Object leftOperand, Object rightOperand)throws ExpressionException {return String.valueOf(leftOperand) + String.valueOf(rightOperand);}}
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);}}1 楼 huangyh 2007-10-16 由具体的Handler负责返回下一个Handler,是不是不大合适,这样很容易出现循环链路。是不是用 BinaryOperatorHandlerDispatcher 来负责 Handler 顺序维护? 2 楼 javatar 2007-10-18 如果匹配方式稳定,用Dispatcher方式是比较好的选择,但职责链可以处理更多特殊情况,因为Handler类可以随时调用nextHandler进行处理。 3 楼 wwlhp 2008-01-12 chain和dispatcher的思路是相同的,只是controlling handler对各种子类handler实例的组织结构不同而已。但都面临着一个问题,如何将子类handler实例注册到总控handler?