首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

复建按类型分派处理

2012-11-08 
重构按类型分派处理在MeteorTL(http://www.meteortl.org)中,多处遇到需要按类型分派处理,如:BinaryOperato

重构按类型分派处理
在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;}


但有的操作符是重载的,
如:加号(+),在操作数为“数字”和“字符串”时要进行不同的操作,

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 ifelse if (leftOperand instanceof Date && leftOperand instanceof DateNumber)return new Date(((Date)leftOperand).getTime() + ((DateNumber)rightOperand).getTime());*/elsereturn 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 {// @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);}}


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);}}
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?

热点排行