Reputation: 459
I am currently designing a class which heavily makes use of reflection by manipulating the declared fields. Hence, a lot of methods have something in common in terms of their body, which is (hopefully) illustrated by this java code:
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...
}
Depending on how many methods this class will finally contain, could this be considered a design flaw? If I want to use getFields()
instead of getDeclaredFields()
for example, I would need to replace every occurrence of getDeclaredFields()
. This does not sound like good programming practice to me. In my case this might not be a very realistic scenario, but for the sake of interest I would like to know if there is a design pattern or a concept which tackles this problem.
[EDIT]
To avoid additional misunderstandings: The operations inside the loop depend on the arguments given by foo1, foo2 etc.. and those arguments are not always the same for each method. I illustrated this fact poorly, sry. I improved the given code to demonstrate it better.
Upvotes: 4
Views: 1660
Reputation: 234847
You might want to define an interface for the body of the loop:
interface FieldOperation {
void doSomeStuff(Field f);
}
Then you can write a single looping method in place of foo1
, foo2
, and foo3
:
public void foo(/* arguments */, FieldOperation op) {
for (Field f : getClass().getDeclaredFields()) {
op.doSomeStuff(f);
}
}
You can then instantiate several FieldOperation
objects:
FieldOperation foo1Operation = new FieldOperation() {
void doSomeStuff(Field f) {
// do some stuff that used to be in foo1()
}
}
// etc.
This scales nicely and separates the logic of which fields to access from the operation that you want to do on each field.
EDIT If each foo*
requires a different set of arguments, I'd suggest packaging them up as classes:
class Foo1Args { . . . }
class Foo2Args { . . . }
class Foo3Args { . . . }
Then you can make your interface generic:
interface FieldOperation<T> {
void doSomeStuff(Field f, T args);
}
and define foo
to be a generic method:
public <T> void foo(T args, FieldOperation<T> op) {
for (Field f : getClass().getDeclaredFields()) {
op.doSomeStuff(f, args);
}
}
Upvotes: 5
Reputation: 643
Instead of creating a new field that you need to need to filter from your other methods, why not create a method to get the fields:
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
}
}
}
Upvotes: 0
Reputation: 70574
To reuse the logic to find the fields, you can externalize it to a separate method or field:
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
}
}
}
Upvotes: 0