众所周知,Displaytag从1.0升级到1.1之后对列修饰器的接口做了改进,在1.1及其后续版本中ColumnDecorator已经不推荐使用,以DisplaytagColumnDecorator替代之,我们可以看到,这两个接口之间的主要不同是集中在接口的decorate方法所接受的参数上,这两个接口中decorate方法的原型分别是:
ColumnDecorator:String decorate(Object columnValue) throws DecoratorException;
DisplaytagColumnDecorator:Object decorate(Object columnValue, PageContext pageContext, MediaTypeEnum media) throws DecoratorException;
至于DisplaytagColumnDecorator中decorate方法的返回类型也和原来不同主要是为了支持链模式,我们在此不予讨论,我想说的是因为传参的不同而使得接口改变说明了Displaytag在设计上的缺陷。假如以后Displaytag的设计者发现列修饰器类在完成其工作时依然需要其余的参数呢,是不是还要再设计一个Displaytag2ColumnDecorator同事废止DisplaytagColumnDecorator呢?这绝不是危言耸听。
还是从JSR的某些API中吸取点经验吧,把decorate方法的参数设计成某个单独的类是不是会更好呢?在Servlet或者JSP规范中经常会见到XxxContext的概念,我个人认为这是一种好办法。假想一下,如果当初Displaytag的ColumnDecorator中的decorate方法的原型设计成下面这样:
Object decorate(DecoratorContext _context) throws DecoratorException;
情况可能就会好的多,当然在它的1.0版本中DecoratorContext的定义可能看起来是下面这样。
public final class DecoratorContext{ private Object decoratedValue; public Object getDecoratedValue() { return decoratedValue; } public void setDecoratedValue(Object decoratedValue) { this.decoratedValue = decoratedValue; } }
ColumnDecorator的实现类可以通过上下文环境获得要装饰的对象: Object value=_context.getDecoratedValue(); 重要的是假如到了1.1版本,我们可以完全不用改变ColumnDecorator接口本身而直接对DecoratorContext进行升级,这时的DecoratorContext看起来是下面这样。
public final class DecoratorContext{ private Object decoratedValue; private PageContext pageContext; private MediaTypeEnum media; //Getters and Setters …… }
如此一来使用1.1版本的用户可以轻松的通过这个上下文环境获取到PageContext或者MediaTypeEnum,而同时又不会伤害到使用旧版本的用户,也就是说旧版本的用户在进行升级时,如果有哪个已存在的列装饰器的实现想要在工作的过程中使用PageContext的话它不必再修改自己所要实现的接口了,让DisplaytagColumnDecorator去见鬼吧。
当然DecoratorContext对象中各个属性的赋值工作是框架本身完成的,使用Displaytag的开发者完全不必担心这一点。
The article is end.