论坛首页 Java企业应用论坛

重构按类型分派处理

浏览 2773 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-10-09  
在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 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);
	}

}
   发表时间:2007-10-16  
由具体的Handler负责返回下一个Handler,是不是不大合适,这样很容易出现循环链路。是不是用 BinaryOperatorHandlerDispatcher  来负责 Handler 顺序维护?
0 请登录后投票
   发表时间:2007-10-18  
如果匹配方式稳定,用Dispatcher方式是比较好的选择,但职责链可以处理更多特殊情况,因为Handler类可以随时调用nextHandler进行处理。
0 请登录后投票
   发表时间:2008-01-12  
chain和dispatcher的思路是相同的,只是controlling handler对各种子类handler实例的组织结构不同而已。但都面临着一个问题,如何将子类handler实例注册到总控handler?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics