一个常用的处理类查找器
class XXHandlerManager { private Map<String, IHandler> handlerKeyToHandler; public void setHandlerKeyToHandler(Map<String,IHandler> handlers) { this. handlerKeyToHandler = handlers; } public IHandler getByBizInfo(xxBizInfo ...args) { String key = generateKey(args); if (handlerKeyToHandler.containsKey(key)) { return handlerKeyToHandler.get(key); } throw HandlerNotFoundException(); } private String generateKey(xxBizInfo ...args) { ..... }}
?看到我们一个业务系统很多这种基本完全一样的代码,觉得或许可以提供一个简单的抽象,从而使代码简单清晰,减少冗余代码。小小思考了下,觉得可以简化抽象的,代码如下:
public class VelocityBaseKeyMapSelector<T> {private final static Logger LOG = LoggerFactory.getLogger(VelocityBaseKeyMapSelector.class);/** * 对象到字符串的转化模板 */private String keyTemplate;/** * 对象字符串到处理器的映射 */private Map<String, T> keyToHandler = Collections.emptyMap();public void setKeyTemplate(String keyTemplate) {this.keyTemplate = keyTemplate;}public void setKeyToHandler(Map<String, T> keyToHandler) {this.keyToHandler = keyToHandler;}public T resolveHandler(Object ...objs) {String key = translateToString(objs);if (keyToHandler.containsKey(key)) {T handler = keyToHandler.get(key);if (LOG.isDebugEnabled()) {LOG.debug("found handler instance ({}) for data ({}).", handler.getClass().getSimpleName(), objs);}return handler;}return null;}/** * 根据对象信息以及Velocity模板生成标识Key */protected String translateToString(Object ...objs) {Map<String, Object> ctx = Maps.newHashMap();ctx.put("args", Lists.newArrayList(objs));return VelocityUtil.rend(ctx, keyTemplate);}}
?通过三个点实现了通用,1.使用泛型使得代码更加通用,对于key觉得没必要提取泛型;2.生成key的业务参数使用变参,表示不限制业务参数的维度;3.把“由业务参数生成key的算法”封装在了keyTemplate模板字符串,样式类似$args.get(0).name,预发满足Velocity语法即可,其中args是所有决定key的参数的List,顺序和方法中顺序一致,综合这三点这个工具类基本完全通用了,最起码我们的业务中的类似代码被消除了,事实上,业务完全不需要扩展,因为已经可变的部分交给配置了。结合Spring就会更舒服,来个小例子:
<bean id="platformBasedSelector" value-ref="xxxHandler" /><entry key="yyy" value-ref="yyyHandler" /><entry key="zzz" value-ref="zzzHandler" /></map></property><property name="keyTemplate" value="$!args.get(0).platformId" /></bean>
?这样每个需要此类功能代码只需要配置一下注入即可,对于key算法的改写也就没必要去修改Java代码了,直接修改keyTemplate对应的模板字符串即可,当然也需要修改上边的handler对应的key。enjoy it!