Java 减少冗余的设计模式

Java 减少冗余的设计模式,java,Java,我目前正在设计一个类,它通过操纵声明的字段来大量使用反射。因此,许多方法在其主体方面都有一些共同点,这(希望)可以通过以下java代码来说明: import java.lang.reflect.Field; public class foo { public void foo1(/* arguments1 */) { for (Field f : getClass().getDeclaredFields()) { // do some stuff

我目前正在设计一个类,它通过操纵声明的字段来大量使用反射。因此,许多方法在其主体方面都有一些共同点,这(希望)可以通过以下java代码来说明:

import java.lang.reflect.Field;

public class foo {
    public void foo1(/* arguments1 */) {
        for (Field f : getClass().getDeclaredFields()) {
            // do some stuff using arguments1
        }
    }

    public void foo2(/* arguments2 */) {
        for (Field f : getClass().getDeclaredFields()) {
            // do some stuff using arguments2
        }
    }

    public void foo3(/* arguments3 */) {
        for (Field f : getClass().getDeclaredFields()) {
            // do some stuff using arguments3
        }
    }

    //and so on...
}
根据该类最终包含的方法的数量,这会被视为设计缺陷吗?例如,如果我想使用
getFields()
而不是
getDeclaredFields()
,我需要替换每次出现的
getDeclaredFields()
。对我来说,这听起来不是一个好的编程实践。在我的例子中,这可能不是一个非常现实的场景,但出于兴趣,我想知道是否有一种设计模式或概念可以解决这个问题

[编辑]


为了避免额外的误解:循环内的操作取决于foo1、foo2等给出的参数。。对于每个方法,这些参数并不总是相同的。我没能很好地说明这个事实,sry。我改进了给定的代码以更好地演示它。

您可能需要为循环体定义一个接口:

interface FieldOperation {
    void doSomeStuff(Field f);
}
然后您可以编写一个单循环方法来代替
foo1
foo2
foo3

public void foo(/* arguments */, FieldOperation op) {
    for (Field f : getClass().getDeclaredFields()) {
        op.doSomeStuff(f);
    }
}
然后,您可以实例化几个
FieldOperation
对象:

FieldOperation foo1Operation = new FieldOperation() {
    void doSomeStuff(Field f) {
        // do some stuff that used to be in foo1()
    }
}
// etc.
这可以很好地扩展,并将要访问的字段的逻辑与要对每个字段执行的操作分开

编辑如果每个
foo*
都需要一组不同的参数,我建议将它们打包为类:

class Foo1Args { . . . }
class Foo2Args { . . . }
class Foo3Args { . . . }
然后,您可以将界面设置为通用界面:

interface FieldOperation<T> {
    void doSomeStuff(Field f, T args);
}

要重用逻辑以查找字段,可以将其外部化为单独的方法或字段:

public class foo {
    private final Field[] fields = getClass().getDeclaredFields();

    public void foo1(/* arguments */) {
        for (Field f : fields) {
            // do some stuff
        }
    }

    public void foo2(/* arguments */) {
        for (Field f : fields) {
            // do some stuff
        }
    }

    public void foo3(/* arguments */) {
        for (Field f : fields) {
            // do some stuff
        }
    }
}

与其创建需要从其他方法筛选的新字段,不如创建一个方法来获取字段:

public class foo {
    private Field[] getDeclaredFields() { 
        return getClass().getDeclaredFields();
    }

    public void foo1(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }

    public void foo2(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }

    public void foo3(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }
}

听起来很合理。不幸的是,循环内的操作依赖于foo1、foo2。。。对于每个方法,这些参数并不总是相同的。也许我应该更好地指出这一点,sry。在这种情况下,您可能无能为力。@user1658887-如果参数有一个标准形式(所有
foo
s都是相同的),那么您可以相应地定义接口。或者,您可以将参数打包为一个类,并使接口通用。@user1658887我添加了一些示例代码,显示了我的意思的概要。@TedHopp谢谢,看起来很棒。您的编辑使这个问题更难解决。为了消除冗余,我们必须知道哪些模式是不变的,你告诉我们事情正在改变,但没有告诉我们它们是如何改变的。唯一不变的部分是,每个方法访问每个声明的字段,并使用相应的参数对其进行“处理”。这种方法实际上是可变的。争论也是如此。老实说,我不知道如何更好地说明它。我已经想到了这种可能性。有趣的副作用:因为“字段”字段很可能对这些方法不感兴趣,所以您必须在每个循环中过滤掉它。无论如何,在我的案例中,这似乎仍然是最好的解决方案,因为我可以将逻辑外部化到一个方法中(正如你所建议的)。正如上面一篇文章所指出的,这就是我目前正在使用的。然而,我更感兴趣的是重用和外部化“字段枚举”。
public class foo {
    private Field[] getDeclaredFields() { 
        return getClass().getDeclaredFields();
    }

    public void foo1(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }

    public void foo2(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }

    public void foo3(/* arguments */) {
        for (Field f : getDeclaredFields()) {
            // do some stuff
        }
    }
}