DRY:最小化Java中的重复代码

DRY:最小化Java中的重复代码,java,dry,Java,Dry,我正在用Java编写一个方法: List<Foo> computeFooList(/* arguments */) { /* snip */ } 第二个添加了字符串表示Foo: List<Foo> computeFooList(/* arguments */) { List<Foo> toReturn = ... ... for (Foo foo : /* some other list of Foo */) {

我正在用Java编写一个方法:

List<Foo> computeFooList(/* arguments */)
{
    /* snip */
}
第二个添加了
字符串
表示
Foo

List<Foo> computeFooList(/* arguments */)
{
    List<Foo> toReturn = ...
    ...
    for (Foo foo : /* some other list of Foo */)
    {
        if (/* some condition */)
        {
            toReturn.add(foo);
        }
    }
    ...
    return toReturn;
}
List<String> computeStringList(/* same arguments */)
{
    List<String> toReturn = ...
    ...
    for (Foo foo : /* some other list of Foo */)
    {
        if (/* some condition */)
        {
            toReturn.add(foo.toString());
        }
    }
    ...
}

有什么好的、优雅的方法可以做到这一点吗?我一直在使用泛型方法,但找不到一种方法可以做到这一点。即使是在反射方面胡闹也没有给我带来任何好处(也许我需要这样的东西?…eww)。

你不能将转换逻辑外部化为一个单独的策略(例如番石榴的
函数
):

computeStringList:

computeList(..., Functions.toStringFunction());
我有一个“SearchFilter”接口和一个“FilterAdapter”抽象类,我使用的方式与此类似。决策逻辑可以从实际向返回列表添加内容开始,以一种通用的方式独立进行。我会检查每个Foo并说“真”包括它或“假”排除它

public interface SearchFilter<T>
{
    public boolean include(T item);
    public Collection<T> apply(Collection<T> items);
}
这可能对您没有帮助,但是
include()
概念应该可以很好地避免重复决策逻辑

您可以有一个
FooFilter extends FilterAdapter
(有时我也会以匿名方式在线实例化这些过滤器),它提供了
include

public FooFilter extends FilterAdapter<Foo>
{
    public boolean include(Foo item)
    {
        if (item.isInvalid()) return false;
        // or any other complex logic you want
        return item.hasGoodThings();
    }
}
public FooFilter扩展FilterAdapter
{
公共布尔包含(Foo项)
{
if(item.isInvalid())返回false;
//或者任何你想要的复杂逻辑
return item.hasGoodThings();
}
}

apply()
方法几乎总是在初始收集和测试
include
上循环,因此它在我的
FilterAdapter
中有一个默认实现,但可以被覆盖。

这有点难看,但我认为这可能有效:

List<Foo> computeFooList(/* args */) {
    return computeEitherList(/* args */, Foo.class);
}

List<String> computeStringList(/* args */) {
    return computeEitherList(/* args */, String.class);
}

private <T> List<T> computeEitherList(/* args */, Class<T> whichType) {
    List<T> rval = new ArrayList<T>();
    for (Foo foo : listOfFoo) {
        // process foo

        if (whichType.equals(Foo.class)) {
            rval.add(whichType.cast(foo));
        }
        else if (whichType.equals(String.class)) {
            rval.add(whichType.cast(foo.toString()));
        }
        else {
            throw new SomeException("Cannot compute list for type " + whichType);
        }
    }
    return rval;
}
列出计算工具列表(/*args*/){
返回computeiteherlist(/*args*/,Foo.class);
}
列表computeStringList(/*args*/){
返回computeiteherlist(/*args*/,String.class);
}
私有列表计算者列表(/*args*/,类whichType){
List rval=new ArrayList();
for(Foo-Foo:listOfFoo){
//过程foo
if(whichType.equals(Foo.class)){
rval.add(whichType.cast(foo));
}
else if(whichType.equals(String.class)){
添加(whichType.cast(foo.toString());
}
否则{
抛出新的SomeException(“无法计算类型的列表”+whichType);
}
}
返回rval;
}

您可能会对这个新的stackexchange站点感兴趣:这看起来确实很有希望。让我来玩玩这个。太棒了!非常感谢。我也已经在用番石榴了。我需要更深入地研究它。
computeList(..., Functions.toStringFunction());
public interface SearchFilter<T>
{
    public boolean include(T item);
    public Collection<T> apply(Collection<T> items);
}
newCollection = myfilter.apply(originalItems);
public FooFilter extends FilterAdapter<Foo>
{
    public boolean include(Foo item)
    {
        if (item.isInvalid()) return false;
        // or any other complex logic you want
        return item.hasGoodThings();
    }
}
List<Foo> computeFooList(/* args */) {
    return computeEitherList(/* args */, Foo.class);
}

List<String> computeStringList(/* args */) {
    return computeEitherList(/* args */, String.class);
}

private <T> List<T> computeEitherList(/* args */, Class<T> whichType) {
    List<T> rval = new ArrayList<T>();
    for (Foo foo : listOfFoo) {
        // process foo

        if (whichType.equals(Foo.class)) {
            rval.add(whichType.cast(foo));
        }
        else if (whichType.equals(String.class)) {
            rval.add(whichType.cast(foo.toString()));
        }
        else {
            throw new SomeException("Cannot compute list for type " + whichType);
        }
    }
    return rval;
}