疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java学习处理逻辑的抽象,processor


 

 
以一个简单的例子来记这个抽象的技巧:
 
 
<问题>
实现三个方法: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的成员变量存在
}
也就是说,数据一点都没有变,只是改变了外界操作数据的方式!