views:

138

answers:

2

I have the following pattern appearing many times in my Java code and was wondering how some of you might refactor it.

Object obj1 = buildObj1();
if (obj1 != null) {
    return obj1;
}

Object obj2 = buildObj2();
if (obj2 != null) {
    return obj2;
}

Object obj3 = buildObj3();
if (obj3 != null) {
    return obj3;
}
+5  A: 

Because Java doesn't have first-class functions, the best you could really do would be to have an interface for "building things", and then do something like this:

for (Builder<T> builder : builders) {
    T obj = builder.build();
    if (obj != null) return obj;
}

The Builder interface would just be something like:

public interface Builder<T> {
    T build();
}

builders in the top snippet is an Iterable<Builder<T>>.

Laurence Gonsalves
I forgot to hit submit. This was my solution!
Stefan Kendall
You may want to write some kind of management class to handle the builders, as well, if the exact order of methods is the same.
Stefan Kendall
@Stefan Kendall - made me laugh.
Allain Lalonde
Would you have these builders internal to the class, or would you promote it to a top level class?
Allain Lalonde
The Builder interface is pretty generic, so I'd probably put that somewhere at the top level. Whether the implementations of that interface are top-level or not depends on how generally useful they are.Actually, that Builder interface is very similar to the Supplier interface in Google Collections (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Supplier.html). You many want to take a look at how Supplier is used in Google Collections, and perhaps even consider using it.
Laurence Gonsalves
+2  A: 

Is that code all called sequentially in the same method? You could use a Factory method that would always return the correct object (either obj1, obj2, or obj3). You could pull the "null or real object" conditional test from each buildObj() method into this factory method so that you always get a valid object from the new factory method.


Alternatively, if you just mean that you have the if (obj != null) tests everywhere you might instead consider using the Null Object Pattern:

Instead of using a null reference to convey absence of an object (for instance, a non-existent customer), one uses an object which implements the expected interface, but whose method body is empty. The advantage of this approach over a working default implementation is that a Null Object is very predictable and has no side effects: it does nothing.

dpdearing