You have already seen this many times yourself, of that I\'m sure:
public SomeObject findSomeObject(Arguments args) {
SomeObject so = queryFirstSource(args);
It depends on some factors you are not defining. Do you have a fixed, rather small set of query…Source
actions as shown in your question or are you rather heading to having a more flexible, extensible list of actions?
In the first case you might consider changing the query…Source
methods to return an Optional
rather than SomeObject
or null
. If you change your methods to be like
Optional queryFirstSource(Arguments args) {
…
}
You can chain them this way:
public SomeObject findSomeObject(Arguments args) {
return queryFirstSource(args).orElseGet(
()->querySecondSource(args).orElseGet(
()->queryThirdSource(args).orElse(null)));
}
If you can’t change them or prefer them to return null
you can still use the Optional
class:
public SomeObject findSomeObject(Arguments args) {
return Optional.ofNullable(queryFirstSource(args)).orElseGet(
()->Optional.ofNullable(querySecondSource(args)).orElseGet(
()->queryThirdSource(args)));
}
If you are looking for a more flexible way for a bigger number of possible queries, it is unavoidable to convert them to some kind of list or stream of Function
s. One possible solution is:
public SomeObject findSomeObject(Arguments args) {
return Stream.>of(
this::queryFirstSource, this::querySecondSource, this::queryThirdSource
).map(f->f.apply(args)).filter(Objects::nonNull).findFirst().orElse(null);
}
This performs the desired operation, however, it will compose the necessary action every time you invoke the method. If you want to invoke this method more often, you may consider composing an operation which you can re-use:
Function find = Stream.>of(
this::queryFirstSource, this::querySecondSource, this::queryThirdSource
).reduce(a->null,(f,g)->a->Optional.ofNullable(f.apply(a)).orElseGet(()->g.apply(a)));
public SomeObject findSomeObject(Arguments args) {
return find.apply(args);
}
So you see, there are more than one way. And it depends on the actual task what direction to go. Sometimes, even the simple if
sequence might be appropriate.