DRY:最小化Java中的重复代码
我正在用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 */) {
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;
}