DRY:尽量减少Java中重复的代码

Mat*_*all 7 java dry

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

List<Foo> computeFooList(/* arguments */)
{
    /* snip */
}
Run Code Online (Sandbox Code Playgroud)

我想用完全相同的逻辑编写第二个方法,但是返回类型不同:

List<String> computeStringList(/* same arguments */)
{
    /* snip */
}
Run Code Online (Sandbox Code Playgroud)

我试图找出一种非hackish方法来最小化两种方法之间重复代码的数量.在只有两个之间的逻辑区别是,将对象添加到所返回的列表中时,第一种方法增加了acutal Foo:

List<Foo> computeFooList(/* arguments */)
{
    List<Foo> toReturn = ...
    ...
    for (Foo foo : /* some other list of Foo */)
    {
        if (/* some condition */)
        {
            toReturn.add(foo);
        }
    }
    ...
    return toReturn;
}
Run Code Online (Sandbox Code Playgroud)

第二个添加了以下String表示Foo:

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

实际上,它并不那么简单.除非我绝对确定它属于那里Foo,toReturn否则我不想添加.因此,该决定是foo使用辅助函数进行的.有两个不同版本的方法,我也需要不同版本的辅助函数 - 最后,我将编写两组近似相同的方法,但是对于一个小的泛型类型.


我可以编写一个包含所有决策逻辑的方法,但是可以生成一个List<Foo>或一个List<String>?是否可以在不使用原始List类型(泛型土地中的不良做法!)或通配符List<?>类型的情况下执行此操作?我想象一个看起来像这样的实现:

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

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

private List<???> computeEitherList(/* args */, Class<?> whichType)
{
    /* snip */
}
Run Code Online (Sandbox Code Playgroud)

这有什么好的,优雅的方式吗?我一直在玩通用方法,但我看不到这样做的方法.即使用反射捣乱也没有把我带到任何地方(也许我需要类似的东西TypeToken?... eww).

axt*_*avt 7

你不能把转化逻辑外化成一个单独的策略(比如番石榴Function<F, T>):

public <T> List<T> computeList(/* arguments */, Function<? super Foo, T> f) {
     List<T> toReturn = ...     ...     
     for (Foo foo : /* some other list of Foo */) {
         if (/* some condition */) {
             toReturn.add(f.apply(foo));
         }
     }
     return toReturn;
} 
Run Code Online (Sandbox Code Playgroud)

computeFooList:

computeList(..., Functions.identity());
Run Code Online (Sandbox Code Playgroud)

computeStringList:

computeList(..., Functions.toStringFunction());
Run Code Online (Sandbox Code Playgroud)