java学习:处理逻辑的抽象,processor
2015-09-13 19:11 14174 阅读(547) 评论(0) 编辑 收藏 举报以一个简单的例子来记这个抽象的技巧:
<问题>
实现三个方法:1、反转字符串;2、反转List;3、反转Set<String>里的所有元素
要求:进行参数校验、结果校验
</问题>
普通写法:(以下三个方法的逻辑都是1.参数校验2.处理3.结果校验,除了2以外基本都一样,多少代码因为各种校验而变得臃肿T_T)
public String reverse(String str){ if(str == null){ //打log,return } String s = StringUtils.reverse(str); if(s == null){ //打log,return } return s; } public List reverse(List list){ if(list == null){ //打log,return } List result = Lists.reverse(list); if(result == null){ //打log,return } return result; } public Set<String> reverse(Set<String> stringSet){ if(stringSet == null){ //打log,return } Set<String> set = Sets.newHashSet(); for(String s : stringSet){ set.add(StringUtils.reverse(s)); } if(set == null){ //打log,return } return set; }
抽象写法:(把传入参数和处理方法交给处理器,校验之类的事情处理器统一完成)
//首先定义接口,只有一个方法,传入一个参数,得到一个返回值 public interface Processor<P,R>{ public R process(P p); } //编写一个处理器,这个方法的逻辑是:1,参数校验2,进行处理3,结果校验 private <P, R> R doSomething(P p, Processor<P, R> processor){ if(p == null){ //打log,return } R result = processor.process(p); if(result == null){ //打log,return } return result; } //下面三个问题要求的方法如下,把参数和处理的方式交个上面的doSomething处理,直接将结果返回就可以了 //可以看到三个方法都只是重写了process方法 public String reverse(String str){ return doSomething(str, new Processor<String, String>() { @Override public String process(String s) { return StringUtils.reverse(s); } }); } public List reverse(List list){ return doSomething(list, new Processor<List, List>() { @Override public List process(List list) { return Lists.reverse(list); } }); } public Set<String> reverse(Set<String> stringSet){ return doSomething(stringSet, new Processor<Set<String>, Set<String>>() { @Override public Set<String> process(Set<String> strings) { Set<String> set = Sets.newHashSet(); for (String s : strings) { set.add(StringUtils.reverse(s)); } return set; } }); }
总结:
对于一些有很多公共操作的方法,可以考虑把它们不同的那一部分抽取出来,公共的部分在一个地方做,这样修改公共的某部分的时候不需要全部改一遍,逻辑也更清楚。
另附:
上面用到的List的reverse是guava提供的Lists.reverse()方法,这个方法的实现很有借鉴学习意义。一般说到反转List,想到的都是把List的元素 n 移到 size-n-1 的地方,时间复杂度为 n,但是guava的实现不一样,时间复杂度为1!它的做法是,重新实现一个reverseList类,继承List,重写List的方法,将正常的List中与位置相关的方法替换,如
get(index){
return forwardList.get(size - 1 - index);//forwardList是转换前的list,作为reserveList的成员变量存在
}
也就是说,数据一点都没有变,只是改变了外界操作数据的方式!
新的一种思路有木有,更详细的实现参看guava源码的具体实现~