浏览 2776 次
锁定老帖子 主题:重构按类型分派处理
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-10-09
http://www.meteortl.org)中,多处遇到需要按类型分派处理,如:BinaryOperatorHandler,UnaryOperatorHandler,PropertyHandler,OutputFormatter,StringSequence等,
在MeteorTL(以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); } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-10-16
由具体的Handler负责返回下一个Handler,是不是不大合适,这样很容易出现循环链路。是不是用 BinaryOperatorHandlerDispatcher 来负责 Handler 顺序维护?
|
|
返回顶楼 | |
发表时间:2007-10-18
如果匹配方式稳定,用Dispatcher方式是比较好的选择,但职责链可以处理更多特殊情况,因为Handler类可以随时调用nextHandler进行处理。
|
|
返回顶楼 | |
发表时间:2008-01-12
chain和dispatcher的思路是相同的,只是controlling handler对各种子类handler实例的组织结构不同而已。但都面临着一个问题,如何将子类handler实例注册到总控handler?
|
|
返回顶楼 | |