模板方法模式应用小记
模板方法:抽取通用的流程(执行逻辑),定义抽象方法,通过定义多个子类以获取不同的实现。
原来的代码:
public void intercept(InterceptorChain chain) throws Throwable {boolean con = true;if(Context.isMe(chain, this)) {con = beforeInvoke(chain.getTarget(), chain.getMethod(), chain.getArgs());Context.meFinished();} else if(allowNesting) {log("allow", "before", chain);con = beforeInvoke(chain.getTarget(), chain.getMethod(), chain.getArgs());} else {log("prevent", "before", chain);}long s = System.nanoTime();try {if (con) {chain.doChain();}} catch (Exception e) {boolean throwEx = true;if(Context.isMe(chain, this)) {throwEx = whenInvokeException(e, chain.getTarget(), chain.getMethod(), chain.getArgs());Context.meFinished();} else if(allowNesting) {log("allow", "after", chain);throwEx = whenInvokeException(e, chain.getTarget(), chain.getMethod(), chain.getArgs());} else {log("prevent", "after", chain);}if (throwEx) {throw e;}} finally {if(Context.isMe(chain, this)) {Object obj = afterInvoke(s,chain.getReturnValue(),chain.getTarget(),chain.getMethod(),chain.getArgs());chain.setReturnValue(obj);Context.meFinished();} else if(allowNesting) {log("allow", "after", chain);Object obj = afterInvoke(s,chain.getReturnValue(),chain.getTarget(),chain.getMethod(),chain.getArgs());chain.setReturnValue(obj);} else {log("prevent", "after", chain);}}}
可以看出这一段重复了3次
if(Context.isMe(chain, this)) { ...} else if(allowNesting) { ...} else { ...}
当我写到第三次时已经抓狂了,这已经不是多几行代码少几行代码的事了,我怕以后有人维护这段代码时会默默诅咒我。
于是套用模板方法,修改如下:
// 定义模板private static abstract class Template {String type;public Template(String type) {super();this.type = type;}boolean intercept(InterceptorChain chain, AbstractInterceptor i,Exception e,long beginTime) {boolean r = true;if (Context.isMe(chain, i)) {r = doIntercept(chain, i,e,beginTime);Context.meFinished();} else if (i.allowNesting) {i.log("allow", type, chain);r = doIntercept(chain, i,e,beginTime);} else {i.log("prevent", type, chain);}return r;}abstract boolean doIntercept(InterceptorChain chain,AbstractInterceptor i,Exception e,long beginTime);} // 定义3个不同的实现。private static final Template before = new Template("before") {boolean doIntercept(InterceptorChain chain, AbstractInterceptor i,Exception e,long beginTime) {return i.beforeInvoke(chain.getTarget(), chain.getMethod(), chain.getArgs());}};private static final Template after = new Template("after") {boolean doIntercept(InterceptorChain chain, AbstractInterceptor i,Exception e,long beginTime) {Object obj = i.afterInvoke(beginTime,chain.getReturnValue(),chain.getTarget(),chain.getMethod(),chain.getArgs());chain.setReturnValue(obj);return true;}};private static final Template whenException = new Template("whenException") {boolean doIntercept(InterceptorChain chain, AbstractInterceptor i,Exception e,long beginTime) { return i. whenInvokeException(e, chain.getTarget(), chain.getMethod(), chain.getArgs());}};// 这是之前的那个方法public void intercept(InterceptorChain chain) throws Throwable {boolean doChain = before.intercept(chain, this, null, 0L);long s = System.nanoTime();try {if (doChain) {chain.doChain();}} catch (Exception e) {if (whenException.intercept(chain, this, e, s)) {throw e;}} finally {after.intercept(chain, this, null, s);}}
代码不见得比原来少,但是心情却舒畅了,符合开心工作的原则。