I'm currently developing the presentation layer of an android app.
The api which I'm using looks something like this:
public interface errorInterface{
public void onError(String reason);
}
public interface if1 extends errorInterface{
public void dataReceived1(Data data);
}
public interface if2 extends errorInterface{
public void dataReceived2(Data data);
}
public void fetchData1(if1 receiver) {}
public void fetchData2(if2 receiver) {}
That is; to fetch data you provide a receiver which will receieve the result of the operation sometime in the future.
This works very well when you need to call only one method at a time, but now I have reached the point when I need to call 10+ such methods in one go, and they need to execute one at a time.
How can I solve this in a flexible and elegant way?
Thanks!
Let me make sure I understand.. you have a series of interfaces if1
, if2
.. ifn
and you want them all to be able to process the data received.
First of all, it would be best if if1
, if2
, etc were all the same interface with your two basic methods: public void dataReceived(Data d)
and public void onError(String reason)
. With that, you can simply pass a List
or Collection
of your receivers to fetchData
and it can iterate over the collection and call dataReceived(d)
on each one.
If, for whatever reason, that's unworkable, I would try an adapter to coax them into a similar interface for fetchData
. For example:
public interface DataReceiver extends ErrorInterface {
public void dataReceived(Data d);
//or just scrap the ErrorInterface all together and make these into 1 interface
}
public class AbstractIFAdapter<T extends ErrorInterface> implements DataReceiver {
private T target;
public AbstractIFAdapter(T target) { this.target = target);
public void onError(String reason) { target.onError(reason); }
protected T getTarget() { return target; }
}
public class IF1Adapter extends AbstractIFAdapter<IF1> {
public IF1Adapter(IF1 target) { super(target); }
public dataReceived(Data d) { getTarget().dataReceived1(d); }
}
public class IF2Adapter extends AbstractIFAdapter<IF2> {
public IF2Adapter(IF2 target) { super(target); }
public dataReceived(Data d) { getTarget().dataReceived2(d); }
}
Now with that in place, we can do something like this:
List<DataReceiver> dataReceivers = new ArrayList<DataReceiver>();
dataReceivers.add(new IF1Adapter(someIf1Implementation));
dataReceivers.add(new IF2Adapter(someIf2Implementation));
fetchData(dataReceivers);
public void fetchData(Collection<DataReceiver> receivers) {
try {
Data d = getSomeData();
for (DataReceiver dr : receivers) {
dr.dataReceived(d);
}
}
catch (Exception e) {
for (DataReceiver dr : receivers) {
dr.onError(e.getMessage());
}
}
}
There are other patterns that may be applicable depending on your exact needs such as visitors or perhaps a chain-of-responsibility type pattern where you chain your receivers together in a linked list type construct and each one calls the next in a recursive construct - this would be nice as fetchData
wouldn't need to know it is getting a collection, it just gets a reference to the top adapter in the chain. So, AbstractIFAdapter
would have a reference to another AbstractIFAdapter
, let's call it next
, and if the reference wasn't null, it would call next.dataReceived(d)
in its own dataReceived
method. Similar idea as ServletFilter
s where each filter gets the ServletRequest
and then calls chain.doFilter(request,response)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With